| 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, element_constructor=None): |
| 92 """De-serializes from element_list to an ``MetaDict``. |
| 93 |
| 94 Args: |
| 95 element_list (list of Element): A list of ``Element`` object. |
| 96 element_constructor (callable): The constructor of ``Element`` object that |
| 97 takes one value in element_list as input. |
| 98 meta_constructor (callable): The contructor of ``MetaDict`` object that |
| 99 only take one dict of MetaObjects as input. |
| 100 |
| 101 Returns: |
| 102 The ``MetaDict`` object contructed from element_list. |
| 103 |
| 104 Raises: |
| 105 Exception: An error occurs when the length of element_list is not equal |
| 106 to the serializer length. |
| 107 """ |
| 108 assert len(self) == len(element_list), Exception( |
| 109 'The element list should have the same length as serializer') |
| 110 |
| 111 meta_constructor = meta_constructor or (lambda x: x) |
| 112 meta_objs = {} |
| 113 index = 0 |
| 114 for key, serializer in self.iteritems(): |
| 115 # Truncate the segment in the element list to construct |
| 116 # the ``MetaObject`` corresponding to ``key``. |
| 117 segment = element_list[index : (index + len(serializer))] |
| 118 if serializer.is_element: |
| 119 meta_objs[key] = serializer.FromList(segment, element_constructor) |
| 120 else: |
| 121 meta_objs[key] = serializer.FromList(segment, meta_constructor, |
| 122 element_constructor) |
| 123 |
| 124 index += len(serializer) |
| 125 |
| 126 return meta_constructor(meta_objs) |
| 127 |
| 128 def _Length(self): |
| 129 """Methods to get the length of the serializer recusively. |
| 130 |
| 131 Note, the length of a serializer is the number of elements, which is also |
| 132 the number of "real values" in a ``MetaDict`` structure. |
| 133 """ |
| 134 if self._length is not None: |
| 135 return self._length |
| 136 |
| 137 self._length = 0 |
| 138 for value in self.itervalues(): |
| 139 self._length += len(value) |
| 140 |
| 141 return self._length |
| 142 |
| 143 def __len__(self): |
| 144 return self._Length() |
| 145 |
| 146 |
| 147 def GetSerializer(meta_object, key=None): |
| 148 """Factory to get a serializer corresponding to a ``MetaObject``. |
| 149 |
| 150 Args: |
| 151 meta_object (MetaObject): ``Element`` or ``MetaDict`` objects. |
| 152 key (callable or None): Key function to sort ``MetaDict`` object. |
| 153 """ |
| 154 if meta_object.is_element: |
| 155 return ElementSerializer() |
| 156 |
| 157 sorted_meta = sorted(meta_object.iteritems(), key=key) |
| 158 ordered_dict = OrderedDict((key, GetSerializer(sub_meta)) |
| 159 for key, sub_meta in sorted_meta) |
| 160 |
| 161 return MetaDictSerializer(ordered_dict) |
| OLD | NEW |