From 8eccfc46bbaaad0e0dca75a009f6e5c353e9acaa Mon Sep 17 00:00:00 2001 From: Shanicky Chen Date: Mon, 3 Apr 2023 22:17:54 +0800 Subject: [PATCH 1/3] Added ethnum crate, defined num256 module, implemented new types, modified existing modules. --- Cargo.lock | 10 ++ src/common/Cargo.toml | 1 + src/common/src/types/mod.rs | 6 + src/common/src/types/num256.rs | 160 ++++++++++++++++++++++ src/common/src/types/to_binary.rs | 2 + src/common/src/util/value_encoding/mod.rs | 4 + 6 files changed, 183 insertions(+) create mode 100644 src/common/src/types/num256.rs diff --git a/Cargo.lock b/Cargo.lock index 0a7d5032f80e1..f6e1f73bf93a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2289,6 +2289,15 @@ dependencies = [ "tower-service", ] +[[package]] +name = "ethnum" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0198b9d0078e0f30dedc7acbb21c974e838fc8fae3ee170128658a98cb2c1c04" +dependencies = [ + "serde", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -5862,6 +5871,7 @@ dependencies = [ "easy-ext", "either", "enum-as-inner", + "ethnum", "fixedbitset", "futures", "futures-async-stream", diff --git a/src/common/Cargo.toml b/src/common/Cargo.toml index 7ab8821d3c815..4c3bbf316b89a 100644 --- a/src/common/Cargo.toml +++ b/src/common/Cargo.toml @@ -35,6 +35,7 @@ derivative = "2" easy-ext = "1" either = "1" enum-as-inner = "0.5" +ethnum = { version = "1", features = ["serde"] } fixedbitset = { version = "0.4", features = ["std"] } futures = { version = "0.3", default-features = false, features = ["alloc"] } futures-async-stream = "0.2" diff --git a/src/common/src/types/mod.rs b/src/common/src/types/mod.rs index ce215124c7437..808b274ad7d2f 100644 --- a/src/common/src/types/mod.rs +++ b/src/common/src/types/mod.rs @@ -47,6 +47,7 @@ pub mod struct_type; pub mod to_binary; pub mod to_text; +mod num256; mod ordered_float; use chrono::{Datelike, NaiveDate, NaiveDateTime, Timelike}; @@ -69,6 +70,7 @@ use crate::array::{ StructValue, }; use crate::error::Result as RwResult; +use crate::types::num256::{Int256, Uint256, Uint256Ref}; pub type F32 = ordered_float::OrderedFloat; pub type F64 = ordered_float::OrderedFloat; @@ -499,6 +501,8 @@ macro_rules! for_all_scalar_variants { { Int16, int16, i16, i16 }, { Int32, int32, i32, i32 }, { Int64, int64, i64, i64 }, + { Int256, int256, Box, &'scalar Int256 }, + { Uint256, uint256, Uint256, Uint256Ref<'scalar> }, { Serial, serial, Serial, Serial }, { Float32, float32, F32, F32 }, { Float64, float64, F64, F64 }, @@ -1029,6 +1033,8 @@ impl ScalarRefImpl<'_> { Self::Int16(v) => v.serialize(ser)?, Self::Int32(v) => v.serialize(ser)?, Self::Int64(v) => v.serialize(ser)?, + Self::Int256(v) => v.serialize(ser)?, + Self::Uint256(v) => v.serialize(ser)?, Self::Serial(v) => v.serialize(ser)?, Self::Float32(v) => v.serialize(ser)?, Self::Float64(v) => v.serialize(ser)?, diff --git a/src/common/src/types/num256.rs b/src/common/src/types/num256.rs new file mode 100644 index 0000000000000..71f19ef5d785f --- /dev/null +++ b/src/common/src/types/num256.rs @@ -0,0 +1,160 @@ +// Copyright 2023 RisingWave Labs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::fmt::Write; +use std::mem; + +use bytes::Bytes; +use ethnum::{I256, U256}; +use postgres_types::{ToSql, Type}; +use serde::{Serialize, Serializer}; +use to_text::ToText; + +use crate::types::to_binary::ToBinary; +use crate::types::{to_text, DataType, Scalar, ScalarRef}; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Default, Hash)] +pub struct Int256(I256); + +#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Default, Hash)] +pub struct Uint256(Box); +#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] +pub struct Uint256Ref<'a>(&'a U256); + +impl Scalar for Uint256 { + type ScalarRefType<'a> = Uint256Ref<'a>; + + fn as_scalar_ref(&self) -> Self::ScalarRefType<'_> { + Uint256Ref(self.0.as_ref()) + } +} + +impl<'a> ScalarRef<'a> for Uint256Ref<'a> { + type ScalarType = Uint256; + + fn to_owned_scalar(&self) -> Self::ScalarType { + Uint256((*self.0).into()) + } + + fn hash_scalar(&self, state: &mut H) { + use std::hash::Hash as _; + self.0.hash(state) + } +} + +impl Serialize for Uint256Ref<'_> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.0.serialize(serializer) + } +} + +impl Uint256Ref<'_> { + #[inline] + pub fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.0.to_le_bytes() + } +} + +impl Int256 { + #[inline] + pub fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.0.to_le_bytes() + } +} + +/// Implement `Scalar` for `Int256`. +impl Scalar for Box { + type ScalarRefType<'a> = &'a Int256; + + fn as_scalar_ref(&self) -> Self::ScalarRefType<'_> { + self.as_ref() + } +} + +/// Implement `ScalarRef` for `Int256`. +impl<'a> ScalarRef<'a> for &'a Int256 { + type ScalarType = Box; + + fn to_owned_scalar(&self) -> Box { + Box::new(Int256(self.0)) + } + + fn hash_scalar(&self, state: &mut H) { + use std::hash::Hash as _; + self.0.hash(state) + } +} + +impl Serialize for Int256 { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.0.serialize(serializer) + } +} + +impl ToText for Uint256Ref<'_> { + fn write(&self, f: &mut W) -> std::fmt::Result { + write!(f, "{}", self.0) + } + + fn write_with_type(&self, _ty: &DataType, f: &mut W) -> std::fmt::Result { + self.write(f) + } +} + +impl ToBinary for Uint256Ref<'_> { + fn to_binary_with_type(&self, _ty: &DataType) -> crate::error::Result> { + let mut output = bytes::BytesMut::new(); + self.0 + .to_be_bytes() + .as_ref() + .to_sql(&Type::ANY, &mut output) + .unwrap(); + Ok(Some(output.freeze())) + } +} + +impl ToText for Int256 { + fn write(&self, f: &mut W) -> std::fmt::Result { + write!(f, "{}", self.0) + } + + fn write_with_type( + &self, + _ty: &crate::types::DataType, + f: &mut W, + ) -> std::fmt::Result { + self.write(f) + } +} + +impl ToBinary for Int256 { + fn to_binary_with_type( + &self, + _ty: &crate::types::DataType, + ) -> crate::error::Result> { + let mut output = bytes::BytesMut::new(); + self.0 + .to_be_bytes() + .as_ref() + .to_sql(&Type::ANY, &mut output) + .unwrap(); + Ok(Some(output.freeze())) + } +} diff --git a/src/common/src/types/to_binary.rs b/src/common/src/types/to_binary.rs index ddebed84b566d..43ddf4704bf3b 100644 --- a/src/common/src/types/to_binary.rs +++ b/src/common/src/types/to_binary.rs @@ -83,6 +83,8 @@ impl ToBinary for ScalarRefImpl<'_> { ScalarRefImpl::Int16(v) => v.to_binary_with_type(ty), ScalarRefImpl::Int32(v) => v.to_binary_with_type(ty), ScalarRefImpl::Int64(v) => v.to_binary_with_type(ty), + ScalarRefImpl::Int256(v) => v.to_binary_with_type(ty), + ScalarRefImpl::Uint256(v) => v.to_binary_with_type(ty), ScalarRefImpl::Serial(v) => v.to_binary_with_type(ty), ScalarRefImpl::Float32(v) => v.to_binary_with_type(ty), ScalarRefImpl::Float64(v) => v.to_binary_with_type(ty), diff --git a/src/common/src/util/value_encoding/mod.rs b/src/common/src/util/value_encoding/mod.rs index eb03fcd7ca675..ebbb6f2d35b13 100644 --- a/src/common/src/util/value_encoding/mod.rs +++ b/src/common/src/util/value_encoding/mod.rs @@ -212,6 +212,8 @@ fn serialize_scalar(value: ScalarRefImpl<'_>, buf: &mut impl BufMut) { ScalarRefImpl::Int16(v) => buf.put_i16_le(v), ScalarRefImpl::Int32(v) => buf.put_i32_le(v), ScalarRefImpl::Int64(v) => buf.put_i64_le(v), + ScalarRefImpl::Int256(v) => buf.put_slice(&v.to_le_bytes()), + ScalarRefImpl::Uint256(v) => buf.put_slice(&v.to_le_bytes()), ScalarRefImpl::Serial(v) => buf.put_i64_le(v.into_inner()), ScalarRefImpl::Float32(v) => buf.put_f32_le(v.into_inner()), ScalarRefImpl::Float64(v) => buf.put_f64_le(v.into_inner()), @@ -238,6 +240,8 @@ fn estimate_serialize_scalar_size(value: ScalarRefImpl<'_>) -> usize { ScalarRefImpl::Int16(_) => 2, ScalarRefImpl::Int32(_) => 4, ScalarRefImpl::Int64(_) => 8, + ScalarRefImpl::Int256(_) => 32, + ScalarRefImpl::Uint256(_) => 32, ScalarRefImpl::Serial(_) => 8, ScalarRefImpl::Float32(_) => 4, ScalarRefImpl::Float64(_) => 8, From 232971929ced5399d45a82a64203a669b563bb17 Mon Sep 17 00:00:00 2001 From: Shanicky Chen Date: Tue, 4 Apr 2023 15:09:36 +0800 Subject: [PATCH 2/3] Implement Uint256 and Int256 with Scalar and ToText/Binary traits --- src/common/src/types/mod.rs | 4 +- src/common/src/types/num256.rs | 196 ++++++++++++--------------------- 2 files changed, 71 insertions(+), 129 deletions(-) diff --git a/src/common/src/types/mod.rs b/src/common/src/types/mod.rs index 808b274ad7d2f..5dfbc83c4df9a 100644 --- a/src/common/src/types/mod.rs +++ b/src/common/src/types/mod.rs @@ -70,7 +70,7 @@ use crate::array::{ StructValue, }; use crate::error::Result as RwResult; -use crate::types::num256::{Int256, Uint256, Uint256Ref}; +use crate::types::num256::{Int256, Int256Ref, Uint256, Uint256Ref}; pub type F32 = ordered_float::OrderedFloat; pub type F64 = ordered_float::OrderedFloat; @@ -501,7 +501,7 @@ macro_rules! for_all_scalar_variants { { Int16, int16, i16, i16 }, { Int32, int32, i32, i32 }, { Int64, int64, i64, i64 }, - { Int256, int256, Box, &'scalar Int256 }, + { Int256, int256, Int256, Int256Ref<'scalar> }, { Uint256, uint256, Uint256, Uint256Ref<'scalar> }, { Serial, serial, Serial, Serial }, { Float32, float32, F32, F32 }, diff --git a/src/common/src/types/num256.rs b/src/common/src/types/num256.rs index 71f19ef5d785f..5173b0bfd0de5 100644 --- a/src/common/src/types/num256.rs +++ b/src/common/src/types/num256.rs @@ -13,6 +13,7 @@ // limitations under the License. use std::fmt::Write; +use std::hash::Hasher; use std::mem; use bytes::Bytes; @@ -24,137 +25,78 @@ use to_text::ToText; use crate::types::to_binary::ToBinary; use crate::types::{to_text, DataType, Scalar, ScalarRef}; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Default, Hash)] -pub struct Int256(I256); - #[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Default, Hash)] pub struct Uint256(Box); #[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] pub struct Uint256Ref<'a>(&'a U256); -impl Scalar for Uint256 { - type ScalarRefType<'a> = Uint256Ref<'a>; - - fn as_scalar_ref(&self) -> Self::ScalarRefType<'_> { - Uint256Ref(self.0.as_ref()) - } -} - -impl<'a> ScalarRef<'a> for Uint256Ref<'a> { - type ScalarType = Uint256; - - fn to_owned_scalar(&self) -> Self::ScalarType { - Uint256((*self.0).into()) - } - - fn hash_scalar(&self, state: &mut H) { - use std::hash::Hash as _; - self.0.hash(state) - } -} - -impl Serialize for Uint256Ref<'_> { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.0.serialize(serializer) - } -} - -impl Uint256Ref<'_> { - #[inline] - pub fn to_le_bytes(self) -> [u8; mem::size_of::()] { - self.0.to_le_bytes() - } -} - -impl Int256 { - #[inline] - pub fn to_le_bytes(self) -> [u8; mem::size_of::()] { - self.0.to_le_bytes() - } -} - -/// Implement `Scalar` for `Int256`. -impl Scalar for Box { - type ScalarRefType<'a> = &'a Int256; - - fn as_scalar_ref(&self) -> Self::ScalarRefType<'_> { - self.as_ref() - } -} - -/// Implement `ScalarRef` for `Int256`. -impl<'a> ScalarRef<'a> for &'a Int256 { - type ScalarType = Box; - - fn to_owned_scalar(&self) -> Box { - Box::new(Int256(self.0)) - } - - fn hash_scalar(&self, state: &mut H) { - use std::hash::Hash as _; - self.0.hash(state) - } -} - -impl Serialize for Int256 { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.0.serialize(serializer) - } -} - -impl ToText for Uint256Ref<'_> { - fn write(&self, f: &mut W) -> std::fmt::Result { - write!(f, "{}", self.0) - } - - fn write_with_type(&self, _ty: &DataType, f: &mut W) -> std::fmt::Result { - self.write(f) - } -} - -impl ToBinary for Uint256Ref<'_> { - fn to_binary_with_type(&self, _ty: &DataType) -> crate::error::Result> { - let mut output = bytes::BytesMut::new(); - self.0 - .to_be_bytes() - .as_ref() - .to_sql(&Type::ANY, &mut output) - .unwrap(); - Ok(Some(output.freeze())) - } -} - -impl ToText for Int256 { - fn write(&self, f: &mut W) -> std::fmt::Result { - write!(f, "{}", self.0) - } - - fn write_with_type( - &self, - _ty: &crate::types::DataType, - f: &mut W, - ) -> std::fmt::Result { - self.write(f) - } +#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Default, Hash)] +pub struct Int256(Box); +#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] +pub struct Int256Ref<'a>(&'a I256); + +macro_rules! impl_common_for_num256 { + ($scalar:ident, $scalar_ref:ident < $gen:tt > , $inner:ty) => { + impl Scalar for $scalar { + type ScalarRefType<'a> = $scalar_ref<$gen>; + + fn as_scalar_ref(&self) -> Self::ScalarRefType<'_> { + $scalar_ref(self.0.as_ref()) + } + } + + impl<$gen> ScalarRef<$gen> for $scalar_ref<$gen> { + type ScalarType = $scalar; + + fn to_owned_scalar(&self) -> Self::ScalarType { + $scalar((*self.0).into()) + } + + fn hash_scalar(&self, state: &mut H) { + use std::hash::Hash as _; + self.0.hash(state) + } + } + + impl Serialize for $scalar_ref<'_> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.0.serialize(serializer) + } + } + + impl $scalar_ref<'_> { + #[inline] + pub fn to_le_bytes(self) -> [u8; mem::size_of::<$inner>()] { + self.0.to_le_bytes() + } + } + + impl ToText for $scalar_ref<'_> { + fn write(&self, f: &mut W) -> std::fmt::Result { + write!(f, "{}", self.0) + } + + fn write_with_type(&self, _ty: &DataType, f: &mut W) -> std::fmt::Result { + self.write(f) + } + } + + impl ToBinary for $scalar_ref<'_> { + fn to_binary_with_type(&self, _ty: &DataType) -> crate::error::Result> { + let mut output = bytes::BytesMut::new(); + self.0 + .to_be_bytes() + .as_ref() + .to_sql(&Type::ANY, &mut output) + .unwrap(); + Ok(Some(output.freeze())) + } + } + }; } -impl ToBinary for Int256 { - fn to_binary_with_type( - &self, - _ty: &crate::types::DataType, - ) -> crate::error::Result> { - let mut output = bytes::BytesMut::new(); - self.0 - .to_be_bytes() - .as_ref() - .to_sql(&Type::ANY, &mut output) - .unwrap(); - Ok(Some(output.freeze())) - } -} +impl_common_for_num256!(Uint256, Uint256Ref<'a>, U256); +impl_common_for_num256!(Int256, Int256Ref<'a>, I256); From d0f301872ce253f72e7eb0761179e15a7e6500ed Mon Sep 17 00:00:00 2001 From: Shanicky Chen Date: Tue, 4 Apr 2023 18:06:08 +0800 Subject: [PATCH 3/3] Update ScalarRefType syntax with generic <$gen>. --- src/common/src/types/num256.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/src/types/num256.rs b/src/common/src/types/num256.rs index 5173b0bfd0de5..c140762a0a6fd 100644 --- a/src/common/src/types/num256.rs +++ b/src/common/src/types/num256.rs @@ -38,7 +38,7 @@ pub struct Int256Ref<'a>(&'a I256); macro_rules! impl_common_for_num256 { ($scalar:ident, $scalar_ref:ident < $gen:tt > , $inner:ty) => { impl Scalar for $scalar { - type ScalarRefType<'a> = $scalar_ref<$gen>; + type ScalarRefType<$gen> = $scalar_ref<$gen>; fn as_scalar_ref(&self) -> Self::ScalarRefType<'_> { $scalar_ref(self.0.as_ref())