mod.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the alphavm library. 3 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 8 // http://www.apache.org/licenses/LICENSE-2.0 9 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 mod boolean; 17 mod field; 18 mod integer; 19 mod scalar; 20 21 use crate::{Literal, LiteralType}; 22 use alphavm_console_network::Network; 23 use alphavm_console_types::{Boolean, integers::Integer, prelude::*}; 24 25 /// Unary operator for casting values of one type to another. 26 pub trait Cast<T: Sized = Self> { 27 /// Casts the value of `self` into a value of type `T`. 28 /// 29 /// This method checks that the cast does not lose any bits of information, 30 /// and returns an error if it does. 31 fn cast(&self) -> Result<T>; 32 } 33 34 impl<N: Network> Literal<N> { 35 /// Casts the literal to the given literal type. 36 /// 37 /// This method checks that the cast does not lose any bits of information, 38 /// and returns an error if it does. 39 /// 40 /// The hierarchy of casting is as follows: 41 /// - (`Address`, `Group`) <-> `Field` <-> `Scalar` <-> `Integer` <-> `Boolean` 42 /// - `Signature` (not supported) 43 /// - `String` (not supported) 44 /// 45 /// Note that casting to left along the hierarchy always preserves information. 46 pub fn cast(&self, to_type: LiteralType) -> Result<Self> { 47 match self { 48 Self::Address(address) => cast_group_to_type(address.to_group(), to_type), 49 Self::Boolean(boolean) => cast_boolean_to_type(boolean, to_type), 50 Self::Field(field) => cast_field_to_type(field, to_type), 51 Self::Group(group) => cast_group_to_type(group, to_type), 52 Self::I8(integer) => cast_integer_to_type(integer, to_type), 53 Self::I16(integer) => cast_integer_to_type(integer, to_type), 54 Self::I32(integer) => cast_integer_to_type(integer, to_type), 55 Self::I64(integer) => cast_integer_to_type(integer, to_type), 56 Self::I128(integer) => cast_integer_to_type(integer, to_type), 57 Self::U8(integer) => cast_integer_to_type(integer, to_type), 58 Self::U16(integer) => cast_integer_to_type(integer, to_type), 59 Self::U32(integer) => cast_integer_to_type(integer, to_type), 60 Self::U64(integer) => cast_integer_to_type(integer, to_type), 61 Self::U128(integer) => cast_integer_to_type(integer, to_type), 62 Self::Scalar(scalar) => cast_scalar_to_type(scalar, to_type), 63 Self::Signature(..) => bail!("Cannot cast a signature literal to another type."), 64 Self::String(..) => bail!("Cannot cast a string literal to another type."), 65 } 66 } 67 } 68 69 /// A helper macro to implement the body of the `cast` methods. 70 macro_rules! impl_cast_body { 71 ($type_name:ident, $cast:ident, $input:expr, $to_type:expr) => { 72 match $to_type { 73 LiteralType::Address => Ok(Literal::Address($input.$cast()?)), 74 LiteralType::Boolean => Ok(Literal::Boolean($input.$cast()?)), 75 LiteralType::Field => Ok(Literal::Field($input.$cast()?)), 76 LiteralType::Group => Ok(Literal::Group($input.$cast()?)), 77 LiteralType::I8 => Ok(Literal::I8($input.$cast()?)), 78 LiteralType::I16 => Ok(Literal::I16($input.$cast()?)), 79 LiteralType::I32 => Ok(Literal::I32($input.$cast()?)), 80 LiteralType::I64 => Ok(Literal::I64($input.$cast()?)), 81 LiteralType::I128 => Ok(Literal::I128($input.$cast()?)), 82 LiteralType::U8 => Ok(Literal::U8($input.$cast()?)), 83 LiteralType::U16 => Ok(Literal::U16($input.$cast()?)), 84 LiteralType::U32 => Ok(Literal::U32($input.$cast()?)), 85 LiteralType::U64 => Ok(Literal::U64($input.$cast()?)), 86 LiteralType::U128 => Ok(Literal::U128($input.$cast()?)), 87 LiteralType::Scalar => Ok(Literal::Scalar($input.$cast()?)), 88 LiteralType::Signature => { 89 bail!(concat!("Cannot cast a ", stringify!($type_name), " literal to a signature type.")) 90 } 91 LiteralType::String => { 92 bail!(concat!("Cannot cast a ", stringify!($type_name), " literal to a string type.")) 93 } 94 } 95 }; 96 } 97 98 /// Casts a boolean literal to the given literal type. 99 fn cast_boolean_to_type<N: Network>(input: &Boolean<N>, to_type: LiteralType) -> Result<Literal<N>> { 100 impl_cast_body!(boolean, cast, input, to_type) 101 } 102 103 /// Casts a field literal to the given literal type. 104 fn cast_field_to_type<N: Network>(input: &Field<N>, to_type: LiteralType) -> Result<Literal<N>> { 105 impl_cast_body!(field, cast, input, to_type) 106 } 107 108 /// Casts a group literal to the given literal type. 109 fn cast_group_to_type<N: Network>(input: &Group<N>, to_type: LiteralType) -> Result<Literal<N>> { 110 match to_type { 111 LiteralType::Address => Ok(Literal::Address(Address::new(*input))), 112 LiteralType::Group => Ok(Literal::Group(*input)), 113 _ => cast_field_to_type(&input.to_x_coordinate(), to_type), 114 } 115 } 116 117 /// Casts an integer literal to the given literal type. 118 fn cast_integer_to_type<N: Network, I: IntegerType>( 119 input: &integers::Integer<N, I>, 120 to_type: LiteralType, 121 ) -> Result<Literal<N>> 122 where 123 i8: TryFrom<I>, 124 i16: TryFrom<I>, 125 i32: TryFrom<I>, 126 i64: TryFrom<I>, 127 i128: TryFrom<I>, 128 u8: TryFrom<I>, 129 u16: TryFrom<I>, 130 u32: TryFrom<I>, 131 u64: TryFrom<I>, 132 u128: TryFrom<I>, 133 { 134 impl_cast_body!(integer, cast, input, to_type) 135 } 136 137 /// Casts a scalar literal to the given literal type. 138 fn cast_scalar_to_type<N: Network>(input: &Scalar<N>, to_type: LiteralType) -> Result<Literal<N>> { 139 impl_cast_body!(scalar, cast, input, to_type) 140 }