Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2017 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 from collections import OrderedDict | |
| 6 | |
| 7 from libs.meta_object import Element | |
| 8 from libs.meta_object import MetaDict | |
| 9 | |
| 10 | |
| 11 class ElementSerializer(Element): | |
| 12 | |
| 13 def ToList(self, element, default=None): | |
| 14 """Serializes an ``Element`` to a list of this single element. | |
| 15 | |
| 16 Args: | |
| 17 element (Element or None): The element to be serialized. If the element | |
| 18 is None, return a list of one default value. | |
| 19 default (Element or None) The default value to set when None element is | |
| 20 provided. | |
| 21 | |
| 22 Returns: | |
| 23 A list of single element. | |
| 24 | |
| 25 Raises: | |
| 26 Exception: An error occurs when the passed-in meta object is not an | |
| 27 ``Element`` object. | |
| 28 """ | |
| 29 if element is None: | |
| 30 return [default] | |
| 31 | |
| 32 assert element.is_element, Exception( | |
| 33 '%s can only serialize Element object.' % self.__class__.__name__) | |
| 34 return [element] | |
| 35 | |
| 36 def FromList(self, element_list, constructor=None): | |
| 37 """De-serializes from element_list to an ``Element``. | |
| 38 | |
| 39 Args: | |
| 40 element_list (list of Element): A list of ``Element`` object. | |
| 41 constructor (callable): contructor of ``Element`` class. | |
| 42 | |
| 43 Returns: | |
| 44 The ``Element`` object in the element_list. | |
| 45 | |
| 46 Raises: | |
| 47 Exception: An error occurs when the element_list is not 1. | |
| 48 """ | |
| 49 assert len(element_list) == len(self), Exception( | |
| 50 'The element list should have the same length as serializer') | |
| 51 | |
| 52 constructor = constructor or (lambda x: x) | |
| 53 return constructor(element_list[0]) | |
| 54 | |
| 55 def __len__(self): | |
| 56 return 1 | |
| 57 | |
| 58 | |
| 59 class MetaDictSerializer(MetaDict): | |
| 60 """Class that serialize a ``MetaDict`` to a list of ``Element``s. | |
| 61 | |
| 62 This class itself is a ``MetaDict``, it has the same structure as the | |
| 63 meta_dict it wants to serialize or de-serialize, and it is using a | |
| 64 ``OrderedDict`` to keep track of the serializing order. | |
| 65 """ | |
| 66 | |
| 67 def __init__(self, value): | |
| 68 super(MetaDictSerializer, self).__init__(value) | |
| 69 self._length = None | |
| 70 | |
| 71 def ToList(self, meta_dict, default=None): | |
| 72 """Serializes a ``MetaDict`` to a list of ``Element``s. | |
| 73 | |
| 74 Args: | |
| 75 meta_dict (MetaDict or None): The element to be serialized. If meta_dict | |
| 76 is None, return a list of default values. | |
| 77 default (Element or None) The default value to set when None meta_dict is | |
| 78 provided. | |
| 79 | |
| 80 Returns: | |
| 81 A list of ``Element``s. | |
| 82 """ | |
| 83 element_list = [] | |
| 84 for key, serializer in self.iteritems(): | |
| 85 sub_meta_dict = meta_dict.get(key) if meta_dict else None | |
| 86 element_list.extend(serializer.ToList(sub_meta_dict, default=default)) | |
| 87 | |
| 88 return element_list | |
| 89 | |
| 90 def FromList(self, element_list, | |
| 91 meta_constructor=None, | |
| 92 element_constructor=None): | |
|
chanli
2017/01/19 02:10:58
Nit: The argument list can be in 2 lines.
Sharu Jiang
2017/01/19 21:00:45
Done.
| |
| 93 """De-serializes from element_list to an ``MetaDict``. | |
| 94 | |
| 95 Args: | |
| 96 element_list (list of Element): A list of ``Element`` object. | |
| 97 element_constructor (callable): The constructor of ``Element`` object that | |
| 98 takes one value in element_list as input. | |
| 99 meta_constructor (callable): The contructor of ``MetaDict`` object that | |
| 100 only take one dict of MetaObjects as input. | |
| 101 | |
| 102 Returns: | |
| 103 The ``MetaDict`` object contructed from element_list. | |
| 104 | |
| 105 Raises: | |
| 106 Exception: An error occurs when the length of element_list is not equal | |
| 107 to the serializer length. | |
| 108 """ | |
| 109 assert len(self) == len(element_list), Exception( | |
| 110 'The element list should have the same length as serializer') | |
| 111 | |
| 112 meta_constructor = meta_constructor or (lambda x: x) | |
| 113 meta_objs = {} | |
| 114 index = 0 | |
| 115 for key, serializer in self.iteritems(): | |
| 116 # Truncate the segment in the element list to construct | |
| 117 # the ``MetaObject`` corresponding to ``key``. | |
| 118 segment = element_list[index : (index + len(serializer))] | |
| 119 if serializer.is_element: | |
| 120 meta_objs[key] = serializer.FromList(segment, element_constructor) | |
| 121 else: | |
| 122 meta_objs[key] = serializer.FromList(segment, meta_constructor, | |
| 123 element_constructor) | |
| 124 | |
| 125 index += len(serializer) | |
| 126 | |
| 127 return meta_constructor(meta_objs) | |
| 128 | |
| 129 def _Length(self): | |
| 130 """Methods to get the length of the serializer recusively. | |
| 131 | |
| 132 Note, the length of a serializer is the number of elements, which is also | |
| 133 the number of "real values" in a ``MetaDict`` structure. | |
| 134 """ | |
| 135 if self._length is not None: | |
| 136 return self._length | |
| 137 | |
| 138 self._length = 0 | |
| 139 for value in self.itervalues(): | |
| 140 self._length += len(value) | |
| 141 | |
| 142 return self._length | |
| 143 | |
| 144 def __len__(self): | |
| 145 return self._Length() | |
| 146 | |
| 147 | |
| 148 def GetSerializer(meta_object, key=None): | |
| 149 """Factory to get a serializer corresponding to a ``MetaObject``. | |
| 150 | |
| 151 Args: | |
| 152 meta_object (MetaObject): ``Element`` or ``MetaDict`` objects. | |
| 153 key (callable or None): Key function to sort ``MetaDict`` object. | |
| 154 """ | |
| 155 if meta_object.is_element: | |
| 156 return ElementSerializer() | |
| 157 | |
| 158 sorted_meta = sorted(meta_object.iteritems(), key=key) | |
| 159 ordered_dict = OrderedDict((key, GetSerializer(sub_meta)) | |
| 160 for key, sub_meta in sorted_meta) | |
| 161 | |
| 162 return MetaDictSerializer(ordered_dict) | |
| OLD | NEW |