Packages
gleam_bson
0.7.0
0.27.0
retired
0.26.0
retired
0.25.0
retired
0.24.0
retired
0.23.0
retired
0.22.0
retired
0.21.0
retired
0.20.0
retired
0.19.0
retired
0.18.0
retired
0.17.0
retired
0.16.0
retired
0.15.0
retired
0.14.0
retired
0.13.0
retired
0.12.0
retired
0.11.0
retired
0.10.1
retired
0.10.0
retired
0.9.0
retired
0.8.0
retired
0.7.0
retired
0.6.0
retired
0.5.0
retired
0.4.0
retired
0.3.0
retired
0.2.0
retired
0.1.0
retired
bson encoder and decoder for gleam
Retired package: Renamed - Republished as bison
Current section
Files
Jump to
Current section
Files
src/bson/encoder.gleam
import gleam/int
import gleam/list
import bson/types
import bson/binary
import bson/object_id
import gleam/bit_string
type Entity {
Entity(kind: types.Kind, value: BitString)
}
pub fn encode(doc: List(#(String, types.Value))) -> BitString {
case document(doc) {
Entity(kind: _, value: value) -> value
}
}
fn document(doc: List(#(String, types.Value))) -> Entity {
let doc =
doc
|> list.reverse
|> list.map(fn(kv) { encode_kv(kv) })
|> bit_string.concat
let size = bit_string.byte_size(doc) + 5
Entity(
kind: types.document,
value: [<<size:32-little>>, doc, <<0>>]
|> bit_string.concat,
)
}
fn encode_kv(pair: #(String, types.Value)) -> BitString {
let key = <<pair.0:utf8, 0>>
let value = case pair.1 {
types.Null -> null()
types.Min -> min()
types.Max -> max()
types.JS(value) -> js(value)
types.Str(value) -> string(value)
types.Array(value) -> array(value)
types.Double(value) -> double(value)
types.Binary(value) -> binary(value)
types.Boolean(value) -> boolean(value)
types.Integer(value) -> integer(value)
types.Document(value) -> document(value)
types.DateTime(value) -> datetime(value)
types.ObjectId(value) -> object_id(value)
types.Timestamp(value) -> timestamp(value)
}
case value {
Entity(kind: kind, value: value) ->
[kind.code, key, value]
|> bit_string.concat
}
}
fn array(list: List(types.Value)) -> Entity {
case list
|> list.index_map(fn(index, item) {
#(
index
|> int.to_string,
item,
)
})
|> list.reverse
|> document {
Entity(kind: _, value: value) -> Entity(kind: types.array, value: value)
}
}
fn string(value: String) -> Entity {
let length = bit_string.byte_size(<<value:utf8>>) + 1
Entity(kind: types.string, value: <<length:32-little, value:utf8, 0>>)
}
fn double(value: Float) -> Entity {
Entity(kind: types.double, value: <<value:little-float>>)
}
fn null() -> Entity {
Entity(kind: types.null, value: <<>>)
}
fn boolean(value: Bool) -> Entity {
case value {
True -> Entity(kind: types.boolean, value: <<1>>)
False -> Entity(kind: types.boolean, value: <<0>>)
}
}
fn integer(value: Int) -> Entity {
case value < types.int32_max && value > types.int32_min {
True -> Entity(kind: types.int32, value: <<value:32-little>>)
False -> Entity(kind: types.int64, value: <<value:64-little>>)
}
}
fn datetime(value: Int) -> Entity {
Entity(kind: types.datetime, value: <<value:64-little>>)
}
fn timestamp(value: Int) -> Entity {
Entity(kind: types.timestamp, value: <<value:64-little>>)
}
fn js(value: String) -> Entity {
let length = bit_string.byte_size(<<value:utf8>>) + 1
Entity(kind: types.js, value: <<length:32-little, value:utf8, 0>>)
}
fn min() -> Entity {
Entity(kind: types.min, value: <<>>)
}
fn max() -> Entity {
Entity(kind: types.max, value: <<>>)
}
fn binary(value: binary.Binary) -> Entity {
let value =
value
|> binary.to_bit_string
let length = bit_string.byte_size(value)
Entity(
kind: types.binary,
value: [<<length:32-little>>, types.generic.code, value]
|> bit_string.concat,
)
}
fn object_id(value: object_id.ObjectId) -> Entity {
Entity(
kind: types.object_id,
value: value
|> object_id.to_bit_string,
)
}