Current section
Files
Jump to
Current section
Files
lib/cql/metadata.ex
defmodule CQL.MetaData do
import CQL.DataTypes.Decoder
require Bitwise
@flags %{
:global_spec => 0x01,
:has_more_pages => 0x02,
:no_metadata => 0x04,
}
def decode(buffer, pk_indices \\ false) do
{meta, buffer} = unpack buffer,
flags: :int,
columns_count: :int,
pk_indices: {&pk_indices/1, when: pk_indices},
paging_state: {:bytes, when: @flags.has_more_pages}
{specs, buffer} = unpack buffer,
columns_specs: {columns_specs(meta), unless: matches(@flags.no_metadata, meta.flags)}
{Map.merge(meta, specs), buffer}
end
def pk_indices(buffer) do
{pk_count, buffer} = int(buffer)
ntimes(pk_count, :short, buffer)
end
def global_spec(buffer) do
unpack buffer,
keyspace: :string,
table: :string
end
def columns_specs(meta) do
fn buffer ->
{global, buffer} = unpack buffer,
spec: {&global_spec/1, when: matches(@flags.global_spec, meta.flags)}
global_spec = Map.get(global, :spec)
ntimes(meta.columns_count, column_spec(global_spec), buffer)
end
end
def column_spec(nil) do
fn buffer ->
unpack buffer,
keyspace: :string,
table: :string,
name: :string,
type: &option/1
end
end
def column_spec(global) do
fn buffer ->
{spec, buffer} = unpack buffer,
name: :string,
type: &option/1
{Map.merge(global, spec), buffer}
end
end
def option(buffer) do
{id, buffer} = short(buffer)
{value, buffer} = case id do
0x00 -> string(buffer)
0x20 -> option(buffer)
0x21 -> options_pair(buffer)
0x22 -> option(buffer)
0x30 -> {nil, buffer} # TODO: UDT
0x31 -> options(buffer)
_ -> {nil, buffer}
end
{CQL.DataTypes.kind({id, value}), buffer}
end
def options(buffer) do
{n, buffer} = short(buffer)
ntimes(n, &option/1, buffer)
end
def options_pair(buffer) do
{option1, buffer} = option(buffer)
{option2, buffer} = option(buffer)
{{option1, option2}, buffer}
end
end