Skip to content

Commit 04de4ee

Browse files
committed
wip
1 parent 8e100ae commit 04de4ee

1 file changed

Lines changed: 109 additions & 59 deletions

File tree

janusgraph_python/structure/io/graphbinaryV1.py

Lines changed: 109 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
# limitations under the License.
1414

1515
from gremlin_python.structure.io.graphbinaryV1 import (
16-
_GraphBinaryTypeIO, StringIO, GraphBinaryReader, GraphBinaryWriter, DataType,
16+
_GraphBinaryTypeIO, StringIO, GraphBinaryReader, GraphBinaryWriter, DataType,
1717
_make_packer,
18-
uint64_pack, uint64_unpack, uint8_pack, uint8_unpack
18+
uint64_pack, uint64_unpack, uint8_pack, uint8_unpack,
1919
)
2020
from janusgraph_python.process.traversal import _JanusGraphP, RelationIdentifier
2121

@@ -24,9 +24,9 @@
2424

2525
class JanusGraphBinaryReader(GraphBinaryReader):
2626
def __init__(self):
27-
# register JanusGraph-specific RelationIdentifier deserializer for custom type
27+
# register JanusGraph-specific deserializer for custom type code
2828
deserializer_map = {
29-
DataType.custom: JanusGraphCustomIO
29+
DataType.custom: JanusGraphBinaryTypeIO
3030
}
3131

3232
GraphBinaryReader.__init__(self, deserializer_map)
@@ -38,17 +38,66 @@ def __init__(self):
3838
(RelationIdentifier, JanusGraphRelationIdentifierIO),
3939
(_JanusGraphP, JanusGraphPSerializer)
4040
]
41+
4142
GraphBinaryWriter.__init__(self, serializer_map)
4243

43-
class _JanusGraphBinaryTypeIO(_GraphBinaryTypeIO):
44+
class JanusGraphBinaryTypeIO(_GraphBinaryTypeIO):
45+
# registry of JanusGraph-specific types with their type_id, type_name and class for deserialization
46+
io_registry = {}
47+
48+
@classmethod
49+
def register_deserializer(cls, type_class):
50+
"""
51+
Method to register a deserializer for a JanusGraph-specific type
52+
"""
53+
cls.io_registry[type_class.graphbinary_type_id] = (type_class.graphbinary_type_name, type_class)
54+
55+
@classmethod
56+
def objectify(cls, buff, reader, nullable=True):
57+
"""
58+
Method used for deserialization of JanusGraph-specific type
59+
"""
60+
return cls.is_null(buff, reader, cls._read_data, nullable)
61+
4462
@classmethod
45-
def custom_type(cls, writer, to_extend, as_value=False):
63+
def _read_data(cls, b, r):
64+
"""
65+
Method used for identifying a JanusGraph-specific type and
66+
find a deserializer class for it
67+
"""
68+
# check if first byte is custom type code byte
69+
if uint8_unpack(b.read(1)) != DataType.custom.value:
70+
return None
71+
72+
# get the custom type name length
73+
custom_type_name_length = uint16_unpack(b.read(2))
74+
custom_type_name = b.read(custom_type_name_length).decode()
75+
76+
# read the custom type id
77+
custom_type_id = uint32_unpack(b.read(4))
78+
79+
# try to get a deserializer class for the JanusGraph-specific type
80+
custom_serializer = cls.io_registry.get(custom_type_id)
81+
if not custom_serializer:
82+
raise NotImplementedError(f"No JanusGraph serializer found for type with id: {custom_type_id}")
83+
84+
# check the type name
85+
if custom_serializer[0] != custom_type_name:
86+
raise NotImplementedError(f"No JanusGraph serializer found for type with name: {custom_type_name}")
87+
88+
return custom_serializer[1].objectify(b, r)
89+
90+
@classmethod
91+
def prefix_bytes_custom_type(cls, writer, to_extend, as_value=False):
92+
"""
93+
Helper method to add a specific byte array prefix while serializing
94+
JanusGraph-specific type as custom type
95+
"""
4696
if to_extend is None:
4797
to_extend = bytearray()
4898

49-
# serializing the custom JanusGraph type
5099
# use the custom type code
51-
if not as_value: #- identifier does not like this if
100+
if not as_value:
52101
to_extend += uint8_pack(DataType.custom.value)
53102

54103
# add the name of the custom JanusGraph type
@@ -61,52 +110,54 @@ def custom_type(cls, writer, to_extend, as_value=False):
61110
if not as_value:
62111
to_extend += uint8_pack(DataType.custom.value)
63112

64-
class JanusGraphPSerializer(_JanusGraphBinaryTypeIO):
113+
class JanusGraphPSerializer(JanusGraphBinaryTypeIO):
65114
graphbinary_type_id = 0x1002
66115
graphbinary_type_name = "janusgraph.P"
67116
python_type = _JanusGraphP
68117

69118
@classmethod
70119
def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
71-
cls.custom_type(writer, to_extend, as_value)
120+
"""
121+
Method to serialize JanusGraph-specific Text predicate
122+
"""
123+
cls.prefix_bytes_custom_type(writer, to_extend, as_value)
72124

73-
# serializing the custom JanusGraph operator
125+
# serialize the custom JanusGraph operator
74126
StringIO.dictify(obj.operator, writer, to_extend, True, False)
75-
127+
76128
# serialize the value
77129
writer.to_dict(obj.value, to_extend)
78130

79131
return to_extend
80132

81-
class JanusGraphRelationIdentifierIO(_JanusGraphBinaryTypeIO):
133+
class JanusGraphRelationIdentifierIO(JanusGraphBinaryTypeIO):
82134
graphbinary_type_id = 0x1001
83135
graphbinary_type_name = "janusgraph.RelationIdentifier"
84136
python_type = RelationIdentifier
85137

86138
long_marker = 0
87139
string_marker = 1
88140

89-
@classmethod
90-
def _write_string(cls, string, writer, to_extend):
91-
b = bytearray()
92-
b.extend(map(ord, string))
93-
b[-1] |= 0x80 # add end marker to the last character
94-
to_extend += b
95-
96141
@classmethod
97142
def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
98-
cls.custom_type(writer, to_extend, as_value)
143+
"""
144+
Method to serialize JanusGraph-specific RelationIdentifier
145+
"""
146+
cls.prefix_bytes_custom_type(writer, to_extend, as_value)
99147

148+
# serialize out vertex ID
100149
if isinstance(obj.out_vertex_id, int):
101150
to_extend += uint8_pack(cls.long_marker)
102151
to_extend += uint64_pack(obj.out_vertex_id)
103152
else:
104153
to_extend += uint8_pack(cls.string_marker)
105154
cls._write_string(obj.out_vertex_id, writer, to_extend)
106155

156+
# serialize edge type ID and relation ID
107157
to_extend += uint64_pack(obj.type_id)
108158
to_extend += uint64_pack(obj.relation_id)
109159

160+
# serialize in vertex ID
110161
if obj.in_vertex_id is None:
111162
to_extend += uint8_pack(cls.long_marker)
112163
to_extend += uint64_pack(0)
@@ -119,33 +170,28 @@ def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
119170

120171
return to_extend
121172

122-
@classmethod
123-
def _read_string(cls, buff):
124-
final_string = ""
125-
while True:
126-
c = 0xFF & uint8_unpack(buff.read(1))
127-
final_string += chr(c & 0x7F)
128-
if c & 0x80 > 0:
129-
break
130-
131-
return final_string
132-
133173
@classmethod
134174
def objectify(cls, b, r):
175+
"""
176+
Method to deserialize JanusGraph-specific RelationIdentifier
177+
"""
135178
if uint8_unpack(b.read(1)) != DataType.custom.value:
136179
raise Exception("Unexpected type while deserializing JanusGraph RelationIdentifier")
137180

138181
# read the next byte that shows if the out vertex id is string or long
139182
out_vertex_id_marker = uint8_unpack(b.read(1))
140183

184+
# deserialize out vertex ID
141185
if out_vertex_id_marker == cls.string_marker:
142186
out_vertex_id = cls._read_string(b)
143187
else:
144188
out_vertex_id = uint64_unpack(b.read(8))
145189

190+
# deserialize edge type ID and relation ID
146191
type_id = uint64_unpack(b.read(8))
147192
relation_id = uint64_unpack(b.read(8))
148193

194+
# deserialize out vertex ID
149195
in_vertex_id_marker = uint8_unpack(b.read(1))
150196
if in_vertex_id_marker == cls.string_marker:
151197
in_vertex_id = cls._read_string(b)
@@ -155,36 +201,40 @@ def objectify(cls, b, r):
155201
in_vertex_id = None
156202

157203
return RelationIdentifier.from_ids(out_vertex_id, type_id, relation_id, in_vertex_id)
204+
205+
@classmethod
206+
def _read_string(cls, buff):
207+
"""
208+
Helper method to read a string represented as byte array.
209+
The length of the string is not known upfront so the byte
210+
array needs to be red until a byte occurs that is marked
211+
with a special end marker
212+
"""
213+
final_string = ""
214+
while True:
215+
c = 0xFF & uint8_unpack(buff.read(1))
216+
final_string += chr(c & 0x7F)
158217

159-
class JanusGraphCustomIO(_GraphBinaryTypeIO):
160-
# list of JanusGraph custom types with their type_id, type_name and class for deserialization
161-
io_registry = {
162-
0x1001: ("janusgraph.RelationIdentifier", JanusGraphRelationIdentifierIO)
163-
}
218+
# check if the character is marked with end marker
219+
# if yes that is the end of the string
220+
if c & 0x80 > 0:
221+
break
164222

165-
@classmethod
166-
def objectify(cls, buff, reader, nullable=True):
167-
return cls.is_null(buff, reader, cls._read_data, nullable)
223+
return final_string
168224

169225
@classmethod
170-
def _read_data(cls, b, r):
171-
# check if first byte is custom byte notation
172-
if uint8_unpack(b.read(1)) != DataType.custom.value:
173-
return None
174-
175-
# get the custom type name length
176-
custom_type_name_length = uint16_unpack(b.read(2))
177-
custom_type_name = b.read(custom_type_name_length).decode()
226+
def _write_string(cls, string, writer, to_extend):
227+
"""
228+
Helper method to create a byte array from a string and
229+
mark the string's last character with special end marker
230+
"""
231+
b = bytearray()
232+
b.extend(map(ord, string))
178233

179-
# read the custom type id
180-
custom_type_id = uint32_unpack(b.read(4))
234+
# add end marker to the last character
235+
b[-1] |= 0x80
181236

182-
custom_serializer = cls.io_registry.get(custom_type_id)
183-
if not custom_serializer:
184-
raise NotImplementedError(f"No JanusGraph serializer found for type with id: {custom_type_id}")
185-
186-
# check the type name
187-
if custom_serializer[0] != custom_type_name:
188-
raise NotImplementedError(f"No JanusGraph serializer found for type with name: {custom_type_name}")
189-
190-
return custom_serializer[1].objectify(b, r)
237+
to_extend += b
238+
239+
# register the JanusGraph-specific RelationIdentifier as deserializer
240+
JanusGraphBinaryTypeIO.register_deserializer(JanusGraphRelationIdentifierIO)

0 commit comments

Comments
 (0)