Add conversion and bitfield operations to Block.
This commit is contained in:
parent
c5429b7e21
commit
57c67cae9e
@ -1,74 +1,107 @@
|
|||||||
use crate::runtime::{
|
use crate::runtime::{
|
||||||
Reference,
|
Reference,
|
||||||
acquire, release,
|
acquire, release,
|
||||||
type_inner, type_key,
|
type_inner, type_key,
|
||||||
block_length,
|
block_length,
|
||||||
block_set, block_get,
|
block_set, block_get,
|
||||||
};
|
block_set_natural, block_get_natural,
|
||||||
use crate::tag;
|
block_set_integer, block_get_integer,
|
||||||
use super::block;
|
block_set_field, block_get_field,
|
||||||
|
};
|
||||||
pub struct Block {
|
use crate::tag;
|
||||||
managed:bool,
|
use super::block;
|
||||||
addr:Reference,
|
|
||||||
}
|
pub struct Block {
|
||||||
impl Block {
|
managed:bool,
|
||||||
pub fn new(size:usize) -> Self
|
addr:Reference,
|
||||||
{
|
}
|
||||||
Self {
|
impl Block {
|
||||||
managed:true,
|
pub fn new(size:usize) -> Self
|
||||||
addr:unsafe {acquire(block(size))},
|
{
|
||||||
}
|
Self {
|
||||||
}
|
managed:true,
|
||||||
|
addr:unsafe {acquire(block(size))},
|
||||||
pub fn with(size:usize, data:Vec<u8>) -> Self
|
}
|
||||||
{
|
}
|
||||||
let mut obj = Self::new(size);
|
|
||||||
obj.set(data);
|
pub fn with(size:usize, data:Vec<u8>) -> Self
|
||||||
return obj;
|
{
|
||||||
}
|
let mut obj = Self::new(size);
|
||||||
|
obj.set(data);
|
||||||
pub fn size(&self) -> usize
|
return obj;
|
||||||
{
|
}
|
||||||
unsafe {block_length(self.addr)}
|
|
||||||
}
|
pub fn size(&self) -> usize
|
||||||
|
{
|
||||||
pub fn set(&mut self, data:Vec<u8>)
|
unsafe {block_length(self.addr)}
|
||||||
{
|
}
|
||||||
let length = unsafe {type_key(type_inner(self.addr.class))};
|
|
||||||
for index in 0..usize::min(data.len(), length) {
|
pub fn set(&mut self, data:Vec<u8>)
|
||||||
unsafe {block_set(self.addr, index, data[index])};
|
{
|
||||||
}
|
let length = unsafe {type_key(type_inner(self.addr.class))};
|
||||||
}
|
for index in 0..usize::min(data.len(), length) {
|
||||||
|
unsafe {block_set(self.addr, index, data[index])};
|
||||||
pub fn get(&self) -> Vec<u8>
|
}
|
||||||
{
|
}
|
||||||
let mut result = Vec::<u8>::new();
|
|
||||||
let length = unsafe {type_key(type_inner(self.addr.class))};
|
pub fn set_u64(&self, data:u64)
|
||||||
if length > 0 {
|
{
|
||||||
result.resize(length, 0);
|
unsafe {block_set_natural(self.addr, data)}
|
||||||
for index in 0..length {
|
}
|
||||||
result[index] = unsafe {block_get(self.addr, index)};
|
|
||||||
}
|
pub fn set_i64(&self, data:i64)
|
||||||
}
|
{
|
||||||
return result;
|
unsafe {block_set_integer(self.addr, data)}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
impl TryFrom<Reference> for Block {
|
pub fn set_field(&mut self, index:usize, length:usize, data:u64)
|
||||||
type Error = ();
|
{
|
||||||
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
|
unsafe { block_set_field(self.addr, index, length, data); }
|
||||||
return if(unsafe {type_key(addr.class)} == tag::BLOCK) {
|
}
|
||||||
Ok(Self { managed:false, addr:addr })
|
|
||||||
}
|
pub fn get(&self) -> Vec<u8>
|
||||||
else {
|
{
|
||||||
Err(())
|
let mut result = Vec::<u8>::new();
|
||||||
}
|
let length = unsafe {type_key(type_inner(self.addr.class))};
|
||||||
}
|
if length > 0 {
|
||||||
}
|
result.resize(length, 0);
|
||||||
impl std::ops::Deref for Block {
|
for index in 0..length {
|
||||||
type Target = Reference;
|
result[index] = unsafe {block_get(self.addr, index)};
|
||||||
fn deref(&self) -> &Self::Target { return &self.addr; }
|
}
|
||||||
}
|
}
|
||||||
impl Drop for Block {
|
return result;
|
||||||
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
|
}
|
||||||
}
|
|
||||||
|
pub fn get_u64(&self) -> u64
|
||||||
|
{
|
||||||
|
unsafe {block_get_natural(self.addr)}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_i64(&self) -> i64
|
||||||
|
{
|
||||||
|
unsafe {block_get_integer(self.addr)}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_field(&self, index:usize, length:usize) -> u64
|
||||||
|
{
|
||||||
|
unsafe {block_get_field(self.addr, index, length)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl TryFrom<Reference> for Block {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
|
||||||
|
return if(unsafe {type_key(addr.class)} == tag::BLOCK) {
|
||||||
|
Ok(Self { managed:false, addr:addr })
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::ops::Deref for Block {
|
||||||
|
type Target = Reference;
|
||||||
|
fn deref(&self) -> &Self::Target { return &self.addr; }
|
||||||
|
}
|
||||||
|
impl Drop for Block {
|
||||||
|
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
|
||||||
|
}
|
||||||
|
@ -549,6 +549,60 @@ extern "C" uint8_t block_get(Reference addr, size_t index)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" uint64_t block_get_natural(Reference addr)
|
||||||
|
{
|
||||||
|
size_t length = type_innerkey(addr.type);
|
||||||
|
uint8_t* data = reinterpret_cast<uint8_t*>(addr.address);
|
||||||
|
uint64_t result = 0;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < length; ++i) {
|
||||||
|
result <<= 8;
|
||||||
|
result |= data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int64_t block_get_integer(Reference addr)
|
||||||
|
{
|
||||||
|
size_t length = type_innerkey(addr.type);
|
||||||
|
uint8_t* data = reinterpret_cast<uint8_t*>(addr.address);
|
||||||
|
int64_t result = 0;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < length; ++i) {
|
||||||
|
result <<= 8;
|
||||||
|
result |= data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" uint64_t block_get_field(Reference addr, size_t index, size_t length)
|
||||||
|
{
|
||||||
|
size_t data_length = type_innerkey(addr.type);
|
||||||
|
size_t byte_start = index >> 3;
|
||||||
|
size_t bit_offset = index & 0x07;
|
||||||
|
size_t byte_length = 1 + ((bit_offset + length) >> 3);
|
||||||
|
size_t byte_end = byte_start + byte_length;
|
||||||
|
size_t mask_offset = ((8 * byte_length) - (length + bit_offset));
|
||||||
|
|
||||||
|
uint64_t mask = ((1 << length) - 1) << mask_offset;
|
||||||
|
uint64_t bits = 0;
|
||||||
|
|
||||||
|
uint8_t* data = reinterpret_cast<uint8_t*>(addr.address);
|
||||||
|
|
||||||
|
size_t i = byte_start;
|
||||||
|
for(; i < data_length && i < byte_end; ++i) {
|
||||||
|
bits <<= 8;
|
||||||
|
bits |= data[i];
|
||||||
|
}
|
||||||
|
for(; i < byte_end; ++i) {
|
||||||
|
bits <<= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bits & mask) >> mask_offset;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void block_set(Reference addr, size_t index, uint8_t value)
|
extern "C" void block_set(Reference addr, size_t index, uint8_t value)
|
||||||
{
|
{
|
||||||
size_t length = type_innerkey(addr.type);
|
size_t length = type_innerkey(addr.type);
|
||||||
@ -557,6 +611,63 @@ extern "C" void block_set(Reference addr, size_t index, uint8_t value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void block_set_natural(Reference addr, uint64_t data)
|
||||||
|
{
|
||||||
|
size_t length = type_innerkey(addr.type);
|
||||||
|
uint8_t* dest = reinterpret_cast<uint8_t*>(addr.address);
|
||||||
|
|
||||||
|
for(size_t i = length; i > 0; --i) {
|
||||||
|
dest[i - 1] = data & 0xFF;
|
||||||
|
data >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void block_set_integer(Reference addr, int64_t data)
|
||||||
|
{
|
||||||
|
size_t length = type_innerkey(addr.type);
|
||||||
|
uint8_t* dest = reinterpret_cast<uint8_t*>(addr.address);
|
||||||
|
|
||||||
|
for(size_t i = length; i > 0; --i) {
|
||||||
|
dest[i - 1] = data & 0xFF;
|
||||||
|
data >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void block_set_field(Reference addr, size_t index, size_t length, uint64_t value)
|
||||||
|
{
|
||||||
|
size_t data_length = type_innerkey(addr.type);
|
||||||
|
size_t byte_start = index >> 3;
|
||||||
|
size_t bit_offset = index & 0x07;
|
||||||
|
size_t byte_length = 1 + ((bit_offset + length) >> 3);
|
||||||
|
size_t byte_end = byte_start + byte_length;
|
||||||
|
size_t mask_offset = ((8 * byte_length) - (length + bit_offset));
|
||||||
|
|
||||||
|
uint64_t mask = ((1 << length) - 1) << mask_offset;
|
||||||
|
uint64_t bits = 0;
|
||||||
|
|
||||||
|
uint8_t* data = reinterpret_cast<uint8_t*>(addr.address);
|
||||||
|
|
||||||
|
size_t byte_index = byte_start;
|
||||||
|
for(; byte_index < data_length && byte_index < byte_end; ++byte_index) {
|
||||||
|
bits <<= 8;
|
||||||
|
bits |= data[byte_index];
|
||||||
|
}
|
||||||
|
for(; byte_index < byte_end; ++byte_index) {
|
||||||
|
bits <<= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
bits &= ~mask;
|
||||||
|
bits |= mask & (value << mask_offset);
|
||||||
|
|
||||||
|
for(; byte_index > data_length; --byte_index) {
|
||||||
|
bits >>= 8;
|
||||||
|
}
|
||||||
|
for(; byte_index > byte_start; --byte_index) {
|
||||||
|
data[byte_index - 1] = bits & 0xFF;
|
||||||
|
bits >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Sequence //
|
// Sequence //
|
||||||
|
|
||||||
|
@ -67,7 +67,13 @@ extern "C" Type::Significant significant_get(Reference addr);
|
|||||||
// Block //
|
// Block //
|
||||||
extern "C" size_t block_length(Reference addr);
|
extern "C" size_t block_length(Reference addr);
|
||||||
extern "C" uint8_t block_get(Reference addr, size_t index);
|
extern "C" uint8_t block_get(Reference addr, size_t index);
|
||||||
|
extern "C" uint64_t block_get_natural(Reference addr);
|
||||||
|
extern "C" int64_t block_get_integer(Reference addr);
|
||||||
|
extern "C" uint64_t block_get_field(Reference addr, size_t index, size_t length);
|
||||||
extern "C" void block_set(Reference addr, size_t index, uint8_t value);
|
extern "C" void block_set(Reference addr, size_t index, uint8_t value);
|
||||||
|
extern "C" void block_set_natural(Reference addr, uint64_t data);
|
||||||
|
extern "C" void block_set_integer(Reference addr, int64_t data);
|
||||||
|
extern "C" void block_set_field(Reference addr, size_t index, size_t length, uint64_t value);
|
||||||
|
|
||||||
// Sequence //
|
// Sequence //
|
||||||
extern "C" size_t sequence_capacity(Reference addr);
|
extern "C" size_t sequence_capacity(Reference addr);
|
||||||
|
@ -83,8 +83,14 @@ extern "C" {
|
|||||||
pub fn significant_get(addr:Reference) -> f64;
|
pub fn significant_get(addr:Reference) -> f64;
|
||||||
|
|
||||||
pub fn block_length(addr:Reference) -> usize;
|
pub fn block_length(addr:Reference) -> usize;
|
||||||
pub fn block_set(addr:Reference, index:usize, data:u8);
|
|
||||||
pub fn block_get(addr:Reference, index:usize) -> u8;
|
pub fn block_get(addr:Reference, index:usize) -> u8;
|
||||||
|
pub fn block_get_natural(addr:Reference) -> u64;
|
||||||
|
pub fn block_get_integer(addr:Reference) -> i64;
|
||||||
|
pub fn block_get_field(addr:Reference, index:usize, length:usize) -> u64;
|
||||||
|
pub fn block_set(addr:Reference, index:usize, data:u8);
|
||||||
|
pub fn block_set_natural(addr:Reference, data:u64);
|
||||||
|
pub fn block_set_integer(addr:Reference, data:i64);
|
||||||
|
pub fn block_set_field(addr:Reference, index:usize, length:usize, data:u64);
|
||||||
|
|
||||||
pub fn sequence_capacity(addr:Reference) -> usize;
|
pub fn sequence_capacity(addr:Reference) -> usize;
|
||||||
pub fn sequence_length(addr:Reference) -> usize;
|
pub fn sequence_length(addr:Reference) -> usize;
|
||||||
|
Reference in New Issue
Block a user