Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CBOR bindings #559

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -350,12 +350,7 @@ poetry.toml
pyrightconfig.json

### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
.vscode

# Local History for Visual Studio Code
.history/
Expand Down
221 changes: 221 additions & 0 deletions awscrt/cbor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0.

import _awscrt

from awscrt import NativeResource
from enum import IntEnum
from typing import Union, Any


class AwsCborType(IntEnum):
# Corresponding to `enum aws_cbor_type` in aws/common/cbor.h
Unknown = 0
UnsignedInt = 1
NegativeInt = 2
Float = 3
Bytes = 4
Text = 5
ArrayStart = 6
MapStart = 7
Tag = 8
Bool = 9
Null = 10
Undefined = 11
Break = 12
IndefBytes = 13
IndefStr = 14
IndefArray = 15
IndefMap = 16


class AwsCborEncoder(NativeResource):
""" Encoder for CBOR """

def __init__(self):
super().__init__()
self._binding = _awscrt.cbor_encoder_new(self)

def get_encoded_data(self) -> bytes:
"""Return the current encoded data as bytes

Returns:
bytes: The encoded data currently
"""
return _awscrt.cbor_encoder_get_encoded_data(self._binding)

def write_int(self, val: int):
# TODO: maybe not support bignum for now. Not needed?
"""Write an int as cbor formatted,
val less than -2^64 will be encoded as Negative bignum for CBOR
val between -2^64 to -1, inclusive, will be encode as negative integer for CBOR
val between 0 to 2^64 - 1, inclusive, will be encoded as unsigned integer for CBOR
val greater than 2^64 - 1 will be encoded as Unsigned bignum for CBOR

Args:
val (int): value to be encoded and written to the encoded data.
"""
assert isinstance(val, int)
val_to_encode = val
if val < 0:
# For negative value, the value to encode is -1 - val.
val_to_encode = -1 - val
bit_len = val_to_encode.bit_length()
if bit_len > 64:
# Bignum
bytes_len = bit_len // 8
if bit_len % 8 > 0:
bytes_len += 1
bytes_val = val_to_encode.to_bytes(bytes_len, "big")
if val < 0:
self.write_tag(AwsCborTags.NegativeBigNum) # tag for negative bignum
else:
self.write_tag(AwsCborTags.UnsignedBigNum) # tag for unsigned bignum
return self.write_bytes(bytes_val)

if val >= 0:
return _awscrt.cbor_encoder_write_unsigned_int(self._binding, val_to_encode)
else:
return _awscrt.cbor_encoder_write_negative_int(self._binding, val_to_encode)

def write_float(self, val: float):
"""Write a double as cbor formatted
If the val can be convert the int without loss of precision,
it will be converted to int to be written to as cbor formatted.

Args:
val (float): value to be encoded and written to the encoded data.
"""
assert isinstance(val, float)
# Floating point numbers are usually implemented using double in C
return _awscrt.cbor_encoder_write_float(self._binding, val)

def write_bytes(self, val: bytes):
"""Write bytes as cbor formatted

Args:
val (bytes): value to be encoded and written to the encoded data.
"""
return _awscrt.cbor_encoder_write_bytes(self._binding, val)

def write_text(self, val: str):
"""Write text as cbor formatted

Args:
val (str): value to be encoded and written to the encoded data.
"""
return _awscrt.cbor_encoder_write_text(self._binding, val)

def write_array_start(self, number_entries: int):
"""Add a start of array element.
A legistic with the `number_entries`
for the cbor data items to be included in the array.
`number_entries` should 0 to 2^64 inclusive.
Otherwise, overflow will be raised.

Args:
number_entries (int): number of entries in the array to be written
"""
if number_entries < 0 or number_entries > 2**64:
raise OverflowError()

return _awscrt.cbor_encoder_write_array_start(self._binding, number_entries)

def write_map_start(self, number_entries: int):
"""Add a start of map element, with the `number_entries`
for the number of pair of cbor data items to be included in the map.
`number_entries` should 0 to 2^64 inclusive.
Otherwise, overflow will be raised.

Args:
number_entries (int): number of entries in the map to be written
"""
if number_entries < 0 or number_entries > 2**64:
raise ValueError()

return _awscrt.cbor_encoder_write_map_start(self._binding, number_entries)

def write_tag(self, tag_number: int):
if tag_number < 0 or tag_number > 2**64:
raise ValueError()

return _awscrt.cbor_encoder_write_tag(self._binding, tag_number)

def write_null(self):
return _awscrt.cbor_encoder_write_simple_types(self._binding, AwsCborType.Null)

def write_bool(self, val: bool):
return _awscrt.cbor_encoder_write_bool(self._binding, val)

def write_list(self, val: list):
return _awscrt.cbor_encoder_write_py_list(self._binding, val)

def write_dict(self, val: dict):
return _awscrt.cbor_encoder_write_py_dict(self._binding, val)

def write_data_item(self, data_item: Any):
"""Generic API to write any type of an data_item as cbor formatted.
TODO: timestamp <-> datetime?? Decimal fraction <-> decimal??

Args:
data_item (Any): any type of data_item. If the type is not supported to be converted to cbor format, ValueError will be raised.
"""
return _awscrt.cbor_encoder_write_data_item(self._binding, data_item)


class AwsCborDecoder(NativeResource):
""" Decoder for CBOR """

def __init__(self, src: bytes):
super().__init__()
self._src = src
self._binding = _awscrt.cbor_decoder_new(src)

def peek_next_type(self) -> AwsCborType:
return AwsCborType(_awscrt.cbor_decoder_peek_type(self._binding))

def get_remaining_bytes_len(self) -> int:
return _awscrt.cbor_decoder_get_remaining_bytes_len(self._binding)

def consume_next_element(self):
return _awscrt.cbor_decoder_consume_next_element(self._binding)

def consume_next_data_item(self):
return _awscrt.cbor_decoder_consume_next_data_item(self._binding)

def pop_next_unsigned_int(self) -> int:
return _awscrt.cbor_decoder_pop_next_unsigned_int(self._binding)

def pop_next_negative_int(self) -> int:
val = _awscrt.cbor_decoder_pop_next_negative_int(self._binding)
return -1 - val

def pop_next_double(self) -> float:
return _awscrt.cbor_decoder_pop_next_float(self._binding)

def pop_next_bool(self) -> bool:
return _awscrt.cbor_decoder_pop_next_bool(self._binding)

def pop_next_bytes(self) -> bytes:
return _awscrt.cbor_decoder_pop_next_bytes(self._binding)

def pop_next_text(self) -> str:
return _awscrt.cbor_decoder_pop_next_text(self._binding)

def pop_next_array_start(self) -> int:
return _awscrt.cbor_decoder_pop_next_array_start(self._binding)

def pop_next_map_start(self) -> int:
return _awscrt.cbor_decoder_pop_next_map_start(self._binding)

def pop_next_tag_val(self) -> int:
return _awscrt.cbor_decoder_pop_next_tag_val(self._binding)

def pop_next_list(self) -> list:
return _awscrt.cbor_decoder_pop_next_py_list(self._binding)

def pop_next_map(self) -> dict:
return _awscrt.cbor_decoder_pop_next_py_dict(self._binding)

def pop_next_data_item(self) -> Any:
return _awscrt.cbor_decoder_pop_next_data_item(self._binding)
2 changes: 1 addition & 1 deletion crt/aws-c-common
Submodule aws-c-common updated 83 files
+1 −1 .clang-tidy
+4 −7 .github/workflows/clang-format.yml
+6 −5 .github/workflows/proof_ci_resources/config.yaml
+10 −1 CMakeLists.txt
+26 −0 THIRD-PARTY-LICENSES.txt
+47 −0 format-check.py
+0 −24 format-check.sh
+2 −4 include/aws/common/atomics.h
+1 −1 include/aws/common/byte_buf.h
+449 −0 include/aws/common/cbor.h
+2 −4 include/aws/common/condition_variable.h
+7 −2 include/aws/common/error.h
+3 −2 include/aws/common/logging.h
+19 −1 include/aws/common/macros.h
+2 −4 include/aws/common/mutex.h
+19 −0 include/aws/common/private/byte_buf.h
+7 −3 include/aws/common/private/external_module_impl.h
+2 −4 include/aws/common/rw_lock.h
+1 −1 include/aws/common/statistics.h
+1 −2 include/aws/common/thread.h
+129 −0 scripts/import_libcbor.py
+8 −3 scripts/latest_submodules.py
+1 −1 source/allocator.c
+3 −1 source/android/logging.c
+19 −0 source/byte_buf.c
+647 −0 source/cbor.c
+12 −2 source/common.c
+19 −0 source/external/libcbor/allocators.c
+425 −0 source/external/libcbor/cbor.c
+74 −0 source/external/libcbor/cbor.h
+131 −0 source/external/libcbor/cbor/arrays.c
+137 −0 source/external/libcbor/cbor/arrays.h
+119 −0 source/external/libcbor/cbor/bytestrings.c
+150 −0 source/external/libcbor/cbor/bytestrings.h
+121 −0 source/external/libcbor/cbor/callbacks.c
+189 −0 source/external/libcbor/cbor/callbacks.h
+14 −0 source/external/libcbor/cbor/cbor_export.h
+163 −0 source/external/libcbor/cbor/common.c
+339 −0 source/external/libcbor/cbor/common.h
+46 −0 source/external/libcbor/cbor/configuration.h
+264 −0 source/external/libcbor/cbor/data.h
+200 −0 source/external/libcbor/cbor/encoding.c
+140 −0 source/external/libcbor/cbor/encoding.h
+189 −0 source/external/libcbor/cbor/floats_ctrls.c
+240 −0 source/external/libcbor/cbor/floats_ctrls.h
+422 −0 source/external/libcbor/cbor/internal/builder_callbacks.c
+85 −0 source/external/libcbor/cbor/internal/builder_callbacks.h
+98 −0 source/external/libcbor/cbor/internal/encoders.c
+41 −0 source/external/libcbor/cbor/internal/encoders.h
+80 −0 source/external/libcbor/cbor/internal/loaders.c
+43 −0 source/external/libcbor/cbor/internal/loaders.h
+57 −0 source/external/libcbor/cbor/internal/memory_utils.c
+50 −0 source/external/libcbor/cbor/internal/memory_utils.h
+33 −0 source/external/libcbor/cbor/internal/stack.c
+53 −0 source/external/libcbor/cbor/internal/stack.h
+95 −0 source/external/libcbor/cbor/internal/unicode.c
+33 −0 source/external/libcbor/cbor/internal/unicode.h
+190 −0 source/external/libcbor/cbor/ints.c
+211 −0 source/external/libcbor/cbor/ints.h
+125 −0 source/external/libcbor/cbor/maps.c
+121 −0 source/external/libcbor/cbor/maps.h
+368 −0 source/external/libcbor/cbor/serialization.c
+168 −0 source/external/libcbor/cbor/serialization.h
+600 −0 source/external/libcbor/cbor/streaming.c
+37 −0 source/external/libcbor/cbor/streaming.h
+142 −0 source/external/libcbor/cbor/strings.c
+183 −0 source/external/libcbor/cbor/strings.h
+46 −0 source/external/libcbor/cbor/tags.c
+74 −0 source/external/libcbor/cbor/tags.h
+1 −1 source/json.c
+1 −1 source/posix/clock.c
+1 −1 source/priority_queue.c
+1 −0 source/windows/thread.c
+11 −0 tests/CMakeLists.txt
+2 −0 tests/assert_test.c
+58 −1 tests/byte_buf_test.c
+489 −0 tests/cbor_test.c
+18 −14 tests/condition_variable_test.c
+9 −7 tests/error_test.c
+87 −0 tests/fuzz/cbor_decoding_transitive.c
+66 −0 tests/fuzz/cbor_double_encode_decode.c
+0 −1 verification/cbmc/proofs/Makefile.common
+4 −1 verification/cbmc/sources/utils.c
Loading
Loading