/ console / program / src / data / literal / cast / mod.rs
mod.rs
  1  // Copyright (c) 2025-2026 ACDC Network
  2  // This file is part of the alphavm library.
  3  //
  4  // Alpha Chain | Delta Chain Protocol
  5  // International Monetary Graphite.
  6  //
  7  // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com).
  8  // They built world-class ZK infrastructure. We installed the EASY button.
  9  // Their cryptography: elegant. Our modifications: bureaucracy-compatible.
 10  // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours.
 11  //
 12  // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0
 13  // All modifications and new work: CC0 1.0 Universal Public Domain Dedication.
 14  // No rights reserved. No permission required. No warranty. No refunds.
 15  //
 16  // https://creativecommons.org/publicdomain/zero/1.0/
 17  // SPDX-License-Identifier: CC0-1.0
 18  
 19  mod boolean;
 20  mod field;
 21  mod integer;
 22  mod scalar;
 23  
 24  use crate::{Literal, LiteralType};
 25  use alphavm_console_network::Network;
 26  use alphavm_console_types::{integers::Integer, prelude::*, Boolean};
 27  
 28  /// Unary operator for casting values of one type to another.
 29  pub trait Cast<T: Sized = Self> {
 30      /// Casts the value of `self` into a value of type `T`.
 31      ///
 32      /// This method checks that the cast does not lose any bits of information,
 33      /// and returns an error if it does.
 34      fn cast(&self) -> Result<T>;
 35  }
 36  
 37  impl<N: Network> Literal<N> {
 38      /// Casts the literal to the given literal type.
 39      ///
 40      /// This method checks that the cast does not lose any bits of information,
 41      /// and returns an error if it does.
 42      ///
 43      /// The hierarchy of casting is as follows:
 44      ///  - (`Address`, `Group`) <-> `Field` <-> `Scalar` <-> `Integer` <-> `Boolean`
 45      ///  - `Signature` (not supported)
 46      ///  - `String` (not supported)
 47      ///
 48      /// Note that casting to left along the hierarchy always preserves information.
 49      pub fn cast(&self, to_type: LiteralType) -> Result<Self> {
 50          match self {
 51              Self::Address(address) => cast_group_to_type(address.to_group(), to_type),
 52              Self::Boolean(boolean) => cast_boolean_to_type(boolean, to_type),
 53              Self::Field(field) => cast_field_to_type(field, to_type),
 54              Self::Group(group) => cast_group_to_type(group, to_type),
 55              Self::I8(integer) => cast_integer_to_type(integer, to_type),
 56              Self::I16(integer) => cast_integer_to_type(integer, to_type),
 57              Self::I32(integer) => cast_integer_to_type(integer, to_type),
 58              Self::I64(integer) => cast_integer_to_type(integer, to_type),
 59              Self::I128(integer) => cast_integer_to_type(integer, to_type),
 60              Self::U8(integer) => cast_integer_to_type(integer, to_type),
 61              Self::U16(integer) => cast_integer_to_type(integer, to_type),
 62              Self::U32(integer) => cast_integer_to_type(integer, to_type),
 63              Self::U64(integer) => cast_integer_to_type(integer, to_type),
 64              Self::U128(integer) => cast_integer_to_type(integer, to_type),
 65              Self::Scalar(scalar) => cast_scalar_to_type(scalar, to_type),
 66              Self::Signature(..) => bail!("Cannot cast a signature literal to another type."),
 67              Self::String(..) => bail!("Cannot cast a string literal to another type."),
 68          }
 69      }
 70  }
 71  
 72  /// A helper macro to implement the body of the `cast` methods.
 73  macro_rules! impl_cast_body {
 74      ($type_name:ident, $cast:ident, $input:expr, $to_type:expr) => {
 75          match $to_type {
 76              LiteralType::Address => Ok(Literal::Address($input.$cast()?)),
 77              LiteralType::Boolean => Ok(Literal::Boolean($input.$cast()?)),
 78              LiteralType::Field => Ok(Literal::Field($input.$cast()?)),
 79              LiteralType::Group => Ok(Literal::Group($input.$cast()?)),
 80              LiteralType::I8 => Ok(Literal::I8($input.$cast()?)),
 81              LiteralType::I16 => Ok(Literal::I16($input.$cast()?)),
 82              LiteralType::I32 => Ok(Literal::I32($input.$cast()?)),
 83              LiteralType::I64 => Ok(Literal::I64($input.$cast()?)),
 84              LiteralType::I128 => Ok(Literal::I128($input.$cast()?)),
 85              LiteralType::U8 => Ok(Literal::U8($input.$cast()?)),
 86              LiteralType::U16 => Ok(Literal::U16($input.$cast()?)),
 87              LiteralType::U32 => Ok(Literal::U32($input.$cast()?)),
 88              LiteralType::U64 => Ok(Literal::U64($input.$cast()?)),
 89              LiteralType::U128 => Ok(Literal::U128($input.$cast()?)),
 90              LiteralType::Scalar => Ok(Literal::Scalar($input.$cast()?)),
 91              LiteralType::Signature => {
 92                  bail!(concat!("Cannot cast a ", stringify!($type_name), " literal to a signature type."))
 93              }
 94              LiteralType::String => {
 95                  bail!(concat!("Cannot cast a ", stringify!($type_name), " literal to a string type."))
 96              }
 97          }
 98      };
 99  }
100  
101  /// Casts a boolean literal to the given literal type.
102  fn cast_boolean_to_type<N: Network>(input: &Boolean<N>, to_type: LiteralType) -> Result<Literal<N>> {
103      impl_cast_body!(boolean, cast, input, to_type)
104  }
105  
106  /// Casts a field literal to the given literal type.
107  fn cast_field_to_type<N: Network>(input: &Field<N>, to_type: LiteralType) -> Result<Literal<N>> {
108      impl_cast_body!(field, cast, input, to_type)
109  }
110  
111  /// Casts a group literal to the given literal type.
112  fn cast_group_to_type<N: Network>(input: &Group<N>, to_type: LiteralType) -> Result<Literal<N>> {
113      match to_type {
114          LiteralType::Address => Ok(Literal::Address(Address::new(*input))),
115          LiteralType::Group => Ok(Literal::Group(*input)),
116          _ => cast_field_to_type(&input.to_x_coordinate(), to_type),
117      }
118  }
119  
120  /// Casts an integer literal to the given literal type.
121  fn cast_integer_to_type<N: Network, I: IntegerType>(
122      input: &integers::Integer<N, I>,
123      to_type: LiteralType,
124  ) -> Result<Literal<N>>
125  where
126      i8: TryFrom<I>,
127      i16: TryFrom<I>,
128      i32: TryFrom<I>,
129      i64: TryFrom<I>,
130      i128: TryFrom<I>,
131      u8: TryFrom<I>,
132      u16: TryFrom<I>,
133      u32: TryFrom<I>,
134      u64: TryFrom<I>,
135      u128: TryFrom<I>,
136  {
137      impl_cast_body!(integer, cast, input, to_type)
138  }
139  
140  /// Casts a scalar literal to the given literal type.
141  fn cast_scalar_to_type<N: Network>(input: &Scalar<N>, to_type: LiteralType) -> Result<Literal<N>> {
142      impl_cast_body!(scalar, cast, input, to_type)
143  }