Skip to content

Commit c1a8582

Browse files
committed
Turn marshal into a proper module
1 parent 3770178 commit c1a8582

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

marshal/marshal.go

+167
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
)
1313

1414
const (
15+
MARSHAL_VERSION = 2
1516
TYPE_NULL = '0'
1617
TYPE_NONE = 'N'
1718
TYPE_FALSE = 'F'
@@ -361,3 +362,169 @@ func ReadPyc(r io.Reader) (obj py.Object, err error) {
361362
// fmt.Printf("header = %v\n", header)
362363
return ReadObject(r)
363364
}
365+
366+
const dump_doc = `dump(value, file[, version])
367+
368+
Write the value on the open file. The value must be a supported type.
369+
The file must be an open file object such as sys.stdout or returned by
370+
open() or os.popen(). It must be opened in binary mode ('wb' or 'w+b').
371+
372+
If the value has (or contains an object that has) an unsupported type, a
373+
ValueError exception is raised — but garbage data will also be written
374+
to the file. The object will not be properly read back by load()
375+
376+
The version argument indicates the data format that dump should use.`
377+
378+
func marshal_dump(self py.Object, args py.Tuple) py.Object {
379+
/*
380+
// XXX Quick hack -- need to do this differently
381+
PyObject *x;
382+
PyObject *f;
383+
int version = Py_MARSHAL_VERSION;
384+
PyObject *s;
385+
PyObject *res;
386+
_Py_IDENTIFIER(write);
387+
388+
if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version))
389+
return NULL;
390+
s = PyMarshal_WriteObjectToString(x, version);
391+
if (s == NULL)
392+
return NULL;
393+
res = _PyObject_CallMethodId(f, &PyId_write, "O", s);
394+
Py_DECREF(s);
395+
return res;
396+
*/
397+
panic("dump not implemented")
398+
}
399+
400+
const load_doc = `load(file)
401+
402+
Read one value from the open file and return it. If no valid value is
403+
read (e.g. because the data has a different Python version’s
404+
incompatible marshal format), raise EOFError, ValueError or TypeError.
405+
The file must be an open file object opened in binary mode ('rb' or
406+
'r+b').
407+
408+
Note: If an object containing an unsupported type was marshalled with
409+
dump(), load() will substitute None for the unmarshallable type.`
410+
411+
func marshal_load(self, f py.Object) py.Object {
412+
/*
413+
PyObject *data, *result;
414+
_Py_IDENTIFIER(read);
415+
RFILE rf;
416+
417+
// Make a call to the read method, but read zero bytes.
418+
// This is to ensure that the object passed in at least
419+
// has a read method which returns bytes.
420+
data = _PyObject_CallMethodId(f, &PyId_read, "i", 0);
421+
if (data == NULL)
422+
return NULL;
423+
if (!PyBytes_Check(data)) {
424+
PyErr_Format(PyExc_TypeError,
425+
"f.read() returned not bytes but %.100s",
426+
data->ob_type->tp_name);
427+
result = NULL;
428+
}
429+
else {
430+
rf.depth = 0;
431+
rf.fp = NULL;
432+
rf.readable = f;
433+
rf.current_filename = NULL;
434+
result = read_object(&rf);
435+
}
436+
Py_DECREF(data);
437+
return result;
438+
*/
439+
panic("load not implemented")
440+
}
441+
442+
const dumps_doc = `dumps(value[, version])
443+
444+
Return the string that would be written to a file by dump(value, file).
445+
The value must be a supported type. Raise a ValueError exception if
446+
value has (or contains an object that has) an unsupported type.
447+
448+
The version argument indicates the data format that dumps should use.`
449+
450+
func marshal_dumps(self py.Object, args py.Tuple) py.Object {
451+
/*
452+
PyObject *x;
453+
int version = Py_MARSHAL_VERSION;
454+
if (!PyArg_ParseTuple(args, "O|i:dumps", &x, &version))
455+
return NULL;
456+
return PyMarshal_WriteObjectToString(x, version);
457+
*/
458+
panic("dumps not implemented")
459+
}
460+
461+
const loads_doc = `loads(bytes)
462+
463+
Convert the bytes object to a value. If no valid value is found, raise
464+
EOFError, ValueError or TypeError. Extra characters in the input are
465+
ignored.`
466+
467+
func marshal_loads(self py.Object, args py.Tuple) py.Object {
468+
/*
469+
RFILE rf;
470+
Py_buffer p;
471+
char *s;
472+
Py_ssize_t n;
473+
PyObject* result;
474+
if (!PyArg_ParseTuple(args, "y*:loads", &p))
475+
return NULL;
476+
s = p.buf;
477+
n = p.len;
478+
rf.fp = NULL;
479+
rf.readable = NULL;
480+
rf.current_filename = NULL;
481+
rf.ptr = s;
482+
rf.end = s + n;
483+
rf.depth = 0;
484+
result = read_object(&rf);
485+
PyBuffer_Release(&p);
486+
return result;
487+
*/
488+
panic("loads not implemented")
489+
}
490+
491+
const module_doc = `This module contains functions that can read and write Python values in
492+
a binary format. The format is specific to Python, but independent of
493+
machine architecture issues.
494+
495+
Not all Python object types are supported; in general, only objects
496+
whose value is independent from a particular invocation of Python can be
497+
written and read by this module. The following types are supported:
498+
None, integers, floating point numbers, strings, bytes, bytearrays,
499+
tuples, lists, sets, dictionaries, and code objects, where it
500+
should be understood that tuples, lists and dictionaries are only
501+
supported as long as the values contained therein are themselves
502+
supported; and recursive lists and dictionaries should not be written
503+
(they will cause infinite loops).
504+
505+
Variables:
506+
507+
version -- indicates the format that the module uses. Version 0 is the
508+
historical format, version 1 shares interned strings and version 2
509+
uses a binary format for floating point numbers.
510+
511+
Functions:
512+
513+
dump() -- write value to a file
514+
load() -- read value from a file
515+
dumps() -- write value to a string
516+
loads() -- read value from a string`
517+
518+
// Initialise the module
519+
func init() {
520+
methods := []*py.Method{
521+
py.NewMethod("dump", marshal_dump, 0, dump_doc),
522+
py.NewMethod("load", marshal_load, 0, load_doc),
523+
py.NewMethod("dumps", marshal_dumps, 0, dumps_doc),
524+
py.NewMethod("loads", marshal_loads, 0, loads_doc),
525+
}
526+
globals := py.StringDict{
527+
"version": py.Int(MARSHAL_VERSION),
528+
}
529+
py.NewModule("marshal", module_doc, methods, globals)
530+
}

0 commit comments

Comments
 (0)