Packages
gleam_bson
0.17.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 bson/md5
import gleam/int
import bson/uuid
import gleam/list
import bson/types
import bson/custom
import bson/generic
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.map(encode_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.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)
types.Binary(types.MD5(value)) -> md5(value)
types.Binary(types.UUID(value)) -> uuid(value)
types.Binary(types.Custom(value)) -> custom(value)
types.Binary(types.Generic(value)) -> generic(value)
types.Regex(#(pattern, options)) -> regex(pattern, options)
}
case value {
Entity(kind: kind, value: value) ->
[kind.code, key, value]
|> bit_string.concat
}
}
fn null() -> Entity {
Entity(kind: types.null, value: <<>>)
}
fn min() -> Entity {
Entity(kind: types.min, value: <<>>)
}
fn max() -> Entity {
Entity(kind: types.max, value: <<>>)
}
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 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 array(value: List(types.Value)) -> Entity {
case
list.index_map(value, fn(index, item) { #(int.to_string(index), item) })
|> document
{
Entity(kind: _, value: value) -> Entity(kind: types.array, value: value)
}
}
fn double(value: Float) -> Entity {
Entity(kind: types.double, value: <<value:little-float>>)
}
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 object_id(value: object_id.ObjectId) -> Entity {
Entity(kind: types.object_id, value: object_id.to_bit_string(value))
}
fn timestamp(value: Int) -> Entity {
Entity(kind: types.timestamp, value: <<value:64-little>>)
}
fn md5(value: md5.MD5) -> Entity {
let value = md5.to_bit_string(value)
let length = bit_string.byte_size(value)
Entity(
kind: types.binary,
value: [<<length:32-little>>, types.md5.code, value]
|> bit_string.concat,
)
}
fn uuid(value: uuid.UUID) -> Entity {
let value = uuid.to_bit_string(value)
let length = bit_string.byte_size(value)
Entity(
kind: types.binary,
value: [<<length:32-little>>, types.uuid.code, value]
|> bit_string.concat,
)
}
fn custom(value: custom.Custom) -> Entity {
let #(code, value) = custom.to_bit_string_with_code(value)
let length = bit_string.byte_size(value)
Entity(
kind: types.binary,
value: [<<length:32-little>>, <<code>>, value]
|> bit_string.concat,
)
}
fn generic(value: generic.Generic) -> Entity {
let value = generic.to_bit_string(value)
let length = bit_string.byte_size(value)
Entity(
kind: types.binary,
value: [<<length:32-little>>, types.generic.code, value]
|> bit_string.concat,
)
}
fn regex(pattern: String, options: String) -> Entity {
Entity(
kind: types.regex,
value: [<<pattern:utf8, 0, options:utf8, 0>>]
|> bit_string.concat,
)
}