Commits

Liam Staskawicz committed 8cb57ab

* since bson needs to be written to a Buf before being sent anyway, might as well write it all to one Buf instead of having multiple intermediate instances hanging around

Comments (0)

Files changed (2)

fan/bson/BsonWriter.fan

     buf := Buf() { endian = Endian.little }
     // because we need to know the length of the object before we can 
     // write it out, we need to assemble it in a Buf first...boo
-    out.writeBuf(writeToBuf(buf, obj))
+    out.writeBuf(writeObject(buf, obj).seek(0))
   }
   
-  private static Buf writeToBuf(Buf b, Str:Obj? obj)
+  private static Buf writeObject(Buf b, Str:Obj? obj)
   {
     lenpos := b.pos()
     b.writeI4(0) // placeholder for len
-    obj.each |val, key| {
-      writeKeyVal(b.out, key, val)
-    }
+    obj.each |val, key| { writeKeyVal(b, key, val) }
     b.write(BsonType.EOO.val) // end of object
-    b.seek(lenpos).writeI4(b.size)
-    return b.seek(0) // rewind to the beginning of the buf
+    // write the len back at the front, then seek to the end
+    return b.seek(lenpos).writeI4(b.size - lenpos).seek(b.size)
   }
   
-  private static Void writeKeyVal(OutStream out, Str key, Obj? val)
+  private static Void writeKeyVal(Buf b, Str key, Obj? val)
   {
-    if (val == null) writeNull(out, key)
-    else if (val is Str) writeStr(out, key, val)
-    else if (val is Date) writeDateTime(out, key, val as DateTime) // convert to DateTime
-    else if (val is DateTime) writeDateTime(out, key, val)
-    else if (val is Buf) writeBinary(out, key, val)
-    else if (val is Int) writeInt(out, key, val)
-    else if (val is Decimal) writeFloat(out, key, (val as Decimal).toFloat())
+    if (val == null) writeNull(b, key)
+    else if (val is Str) writeStr(b, key, val)
+    else if (val is Date) writeDateTime(b, key, val as DateTime) // convert to DateTime
+    else if (val is DateTime) writeDateTime(b, key, val)
+    else if (val is Buf) writeBinary(b, key, val)
+    else if (val is Int) writeInt(b, key, val)
+    else if (val is Decimal) writeFloat(b, key, (val as Decimal).toFloat())
     // todo - maybe maintain Decimal somehow?
-    else if (val is Float) writeFloat(out, key, val)
-    else if (val is ObjectID) writeOID(out, key, val)
-    else if (val is List) writeArray(out, key, val)
-    else if (val is Bool) writeBool(out, key, val)
-    else if (val is Map) writeMap(out, key, val)
-    else if (val is CodeWScope) writeCodeWScope(out, key, val)
+    else if (val is Float) writeFloat(b, key, val)
+    else if (val is ObjectID) writeOID(b, key, val)
+    else if (val is List) writeArray(b, key, val)
+    else if (val is Bool) writeBool(b, key, val)
+    else if (val is Map) writeMap(b, key, val)
+    else if (val is CodeWScope) writeCodeWScope(b, key, val)
     // else if (val is Regex) writeRegex(out, key, val)
     else throw Err("unknown BSON type - can't serialize ${Type.of(val).qname}")
   }
     out.writeChars(str).write(0)
   }
   
-  private static Void writeStr(OutStream out, Str str, Str val)
+  private static Void writeStr(Buf b, Str str, Str val)
   {
-    out.write(BsonType.STRING.val)
-    writeCStr(out, str)
-    out.writeI4(val.size + 1) // account for null terminator
-    writeCStr(out, val)
+    b.write(BsonType.STRING.val)
+    writeCStr(b.out, str)
+    b.writeI4(val.size + 1) // account for null terminator
+    writeCStr(b.out, val)
   }
   
-  private static Void writeNull(OutStream out, Str key)
+  private static Void writeNull(Buf b, Str key)
   {
-    out.write(BsonType.NULL.val)
-    writeCStr(out, key)
+    b.write(BsonType.NULL.val)
+    writeCStr(b.out, key)
   }
   
-  private static Void writeBool(OutStream out, Str key, Bool b)
+  private static Void writeBool(Buf b, Str key, Bool tf)
   {
-    out.write(BsonType.BOOLEAN.val)
-    writeCStr(out, key)
-    out.write(b ? 0x01 : 0x00)
+    b.write(BsonType.BOOLEAN.val)
+    writeCStr(b.out, key)
+    b.write(tf ? 0x01 : 0x00)
   }
   
-  private static Void writeInt(OutStream out, Str key, Int i)
+  private static Void writeInt(Buf b, Str key, Int i)
   {
-    out.write(BsonType.NUMBER_LONG.val)
-    writeCStr(out, key)
-    out.writeI8(i)
+    b.write(BsonType.NUMBER_LONG.val)
+    writeCStr(b.out, key)
+    b.writeI8(i)
   }
   
-  private static Void writeFloat(OutStream out, Str key, Float f)
+  private static Void writeFloat(Buf b, Str key, Float f)
   {
-    out.write(BsonType.NUMBER.val)
-    writeCStr(out, key)
-    out.writeF8(f)
+    b.write(BsonType.NUMBER.val)
+    writeCStr(b.out, key)
+    b.writeF8(f)
   }
   
-  private static Void writeDateTime(OutStream out, Str key, DateTime d)
+  private static Void writeDateTime(Buf b, Str key, DateTime d)
   {
-    out.write(BsonType.DATE.val)
-    writeCStr(out, key)
-    out.writeI8(d.toJava())
+    b.write(BsonType.DATE.val)
+    writeCStr(b.out, key)
+    b.writeI8(d.toJava())
   }
   
   // bson array is really a map with stringified indexes
-  private static Void writeArray(OutStream out, Str key, List list)
+  private static Void writeArray(Buf b, Str key, List list)
   {
-    out.write(BsonType.ARRAY.val)
-    writeCStr(out, key)
-    b := Buf() { endian = Endian.little }
+    b.write(BsonType.ARRAY.val)
+    writeCStr(b.out, key)
     m := Str:Obj?[:] { ordered = true }
-    list.each |val, i| {
-      m[i.toStr] = val
-    }
-    out.writeBuf(writeToBuf(b, m))
+    list.each |val, i| { m[i.toStr] = val }
+    writeObject(b, m)
   }
   
-  private static Void writeMap(OutStream out, Str key, Map m)
+  private static Void writeMap(Buf b, Str key, Map m)
   {
-    out.write(BsonType.OBJECT.val)
-    writeCStr(out, key)
-    b := Buf() { endian = Endian.little }
-    out.writeBuf(writeToBuf(b, m))
+    b.write(BsonType.OBJECT.val)
+    writeCStr(b.out, key)
+    writeObject(b, m)
   }
   
-  private static Void writeBinary(OutStream out, Str key, Buf b, BsonBinType bbt := BsonBinType.LENGTH)
+  private static Void writeBinary(Buf b, Str key, Buf bin, BsonBinType bbt := BsonBinType.LENGTH)
   {
-    out.write(BsonType.BINARY.val)
-    writeCStr(out, key)
-    out.writeI4(b.size)
-    out.write(bbt.val)
+    b.write(BsonType.BINARY.val)
+    writeCStr(b.out, key)
+    b.writeI4(bin.size).write(bbt.val)
     // don't disturb the pos
-    p := b.pos
-    out.writeBuf(b)
-    b.seek(p)
+    p := bin.pos
+    b.writeBuf(bin)
+    bin.seek(p)
   }
   
-  private static Void writeOID(OutStream out, Str key, ObjectID oid)
+  private static Void writeOID(Buf b, Str key, ObjectID oid)
   {
-    out.write(BsonType.OID.val)
-    writeCStr(out, key)
-    oid.write(out)
+    b.write(BsonType.OID.val)
+    writeCStr(b.out, key)
+    oid.write(b.out)
   }
   
-  private static Void writeCodeWScope(OutStream out, Str key, CodeWScope cws)
+  private static Void writeCodeWScope(Buf b, Str key, CodeWScope cws)
   {
-    out.write(BsonType.CODE_W_SCOPE.val)
-    writeCStr(out, key)
-    b := Buf() { endian = Endian.little }
-    writeToBuf(b, cws.scope)
-    out.writeI4(8 + cws.code.size + 1 + b.size)   // total size
-    out.writeI4(cws.code.size + 1)                // size of code str
-    writeCStr(out, cws.code)                      // code str
-    out.writeBuf(b)                               // scope
+    b.write(BsonType.CODE_W_SCOPE.val)
+    writeCStr(b.out, key)
+
+    writeObject(b, cws.scope)
+    b.writeI4(8 + cws.code.size + 1 + b.size)   // total size
+    b.writeI4(cws.code.size + 1)                // size of code str
+    writeCStr(b.out, cws.code)                  // code str
+    b.writeBuf(b.seek(0))                       // scope
   }
   
-  private static Void writeMinKey(OutStream out, Str key)
+  private static Void writeMinKey(Buf b, Str key)
   {
-    out.write(BsonType.MINKEY.val)
-    writeCStr(out, key)
+    b.write(BsonType.MINKEY.val)
+    writeCStr(b.out, key)
   }
   
-  private static Void writeMaxKey(OutStream out, Str key)
+  private static Void writeMaxKey(Buf b, Str key)
   {
-    out.write(BsonType.MAXKEY.val)
-    writeCStr(out, key)
+    b.write(BsonType.MAXKEY.val)
+    writeCStr(b.out, key)
   }
   
 }

fan/bson/CodeWScope.fan

   const Str code
   const Str:Obj? scope
   
-  new make(Str code, Str:Obj? scope)
+  new make(Str code, Str:Obj? scope := [:])
   {
     this.code = code
     this.scope = scope
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.