|  | # Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file | 
|  | # for details. All rights reserved. Use of this source code is governed by a | 
|  | # BSD-style license that can be found in the LICENSE file. | 
|  | ''' | 
|  | This Encoder shares a lot in common with protobufs.  It uses variable length | 
|  | ints and size-encoded strings and binary values.  Other than being hugely | 
|  | stripped down, the major conceptual difference is that this encoding | 
|  | is UTF8 "safe".  This means that it generates a form that should be passed | 
|  | on the wire as UTF8 and then can be very efficiently decoded by JS in the | 
|  | browser which natively handles these kinds of strings.  To stay efficient in | 
|  | this range, all numeric data is encoded in only 7 bits. | 
|  | ''' | 
|  |  | 
|  | import base64 | 
|  |  | 
|  |  | 
|  | class Encoder: | 
|  |  | 
|  | def __init__(self): | 
|  | self.data = [] | 
|  |  | 
|  | def writeInt(self, value): | 
|  | '''Uses a 7-bit per byte encoding to stay UTF-8 "safe".''' | 
|  | bits = value & 0x3f | 
|  | value >>= 6 | 
|  | while value: | 
|  | self.data.append(chr(0x40 | bits)) | 
|  | bits = value & 0x3f | 
|  | value >>= 6 | 
|  | self.data.append(chr(bits)) | 
|  |  | 
|  | def writeBool(self, b): | 
|  | self.data.append(('F', 'T')[b]) | 
|  |  | 
|  | def writeString(self, s): | 
|  | if not s: s = '' | 
|  | self.writeInt(len(s)) | 
|  | self.data.append(s) | 
|  |  | 
|  | def writeBinary(self, s): | 
|  | '''Encode binary data using base64.  This is less efficient than a 7-bit | 
|  | encoding would be; however, it can be decoded much faster on most | 
|  | browsers due to native support for the format.''' | 
|  | v = base64.b64encode(s) | 
|  | self.writeInt(len(v)) | 
|  | self.data.append(v) | 
|  |  | 
|  | def writeList(self, l): | 
|  | self.writeInt(len(l)) | 
|  | for i in l: | 
|  | i.encode(self) | 
|  |  | 
|  | def writeRaw(self, s): | 
|  | self.data.append(s) | 
|  |  | 
|  | def finish(self): | 
|  | d = ''.join(self.data) | 
|  | return _encVarInt(len(d)) + d | 
|  |  | 
|  | def getRaw(self): | 
|  | return ''.join(self.data) |