1#![cfg_attr(not(feature = "std"), no_std)]
4
5#[cfg(not(feature = "std"))]
6extern crate alloc;
7
8#[cfg(not(feature = "std"))]
9use alloc::boxed::Box;
10use core::fmt;
11
12pub mod bigint;
13pub mod byte_array;
14pub mod casts;
15pub mod collection_arithmetics;
16pub mod extract_matches;
17#[cfg(feature = "std")]
18pub mod graph_algos;
19pub mod iterators;
20#[cfg(feature = "env_logger")]
21pub mod logging;
22pub mod ordered_hash_map;
23pub mod ordered_hash_set;
24pub mod unordered_hash_map;
25pub mod unordered_hash_set;
26
27pub trait OptionFrom<T>
29where
30 Self: Sized,
31{
32 fn option_from(other: T) -> Option<Self>;
33}
34
35pub fn write_comma_separated<Iter: IntoIterator<Item = V>, V: core::fmt::Display>(
36 f: &mut fmt::Formatter<'_>,
37 values: Iter,
38) -> fmt::Result {
39 let mut iter = values.into_iter();
40 if let Some(value) = iter.next() {
41 write!(f, "{value}")?;
42 }
43 for value in iter {
44 write!(f, ", {value}")?;
45 }
46 Ok(())
47}
48
49pub trait OptionHelper {
51 fn on_none<F: FnOnce()>(self, f: F) -> Self;
52}
53impl<T> OptionHelper for Option<T> {
54 fn on_none<F: FnOnce()>(self, f: F) -> Self {
55 if self.is_none() {
56 f();
57 }
58 self
59 }
60}
61
62pub fn borrow_as_box<T: Default, R, F: FnOnce(Box<T>) -> (R, Box<T>)>(ptr: &mut T, f: F) -> R {
78 let (res, boxed) = f(Box::new(core::mem::take(ptr)));
81 *ptr = *boxed;
82 res
83}
84
85pub trait LookupIntern<'a, DynDbGroup: ?Sized, LongId> {
87 fn lookup_intern(&self, db: &(impl Upcast<DynDbGroup> + ?Sized)) -> LongId;
88}
89pub trait Intern<'a, DynDbGroup: ?Sized, ShortId> {
90 fn intern(self, db: &(impl Upcast<DynDbGroup> + ?Sized)) -> ShortId;
91}
92
93#[macro_export]
102macro_rules! define_short_id {
103 ($short_id:ident, $long_id:path, $db:ident, $lookup:ident, $intern:ident) => {
104 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
105 pub struct $short_id(salsa::InternId);
106 impl<'a> cairo_lang_utils::LookupIntern<'a, dyn $db + 'a, $long_id> for $short_id {
107 fn lookup_intern(
108 &self,
109 db: &(impl cairo_lang_utils::Upcast<dyn $db + 'a> + ?Sized),
110 ) -> $long_id {
111 $db::$lookup(db.upcast(), *self)
112 }
113 }
114 impl<'a> cairo_lang_utils::Intern<'a, dyn $db + 'a, $short_id> for $long_id {
115 fn intern(
116 self,
117 db: &(impl cairo_lang_utils::Upcast<dyn $db + 'a> + ?Sized),
118 ) -> $short_id {
119 $db::$intern(db.upcast(), self)
120 }
121 }
122 impl salsa::InternKey for $short_id {
123 fn from_intern_id(salsa_id: salsa::InternId) -> Self {
124 Self(salsa_id)
125 }
126
127 fn as_intern_id(&self) -> salsa::InternId {
128 self.0
129 }
130 }
131 impl<T: ?Sized + cairo_lang_utils::Upcast<dyn $db + 'static>>
133 cairo_lang_debug::DebugWithDb<T> for $short_id
134 {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &T) -> std::fmt::Result {
136 use core::fmt::Debug;
137
138 use cairo_lang_debug::helper::Fallback;
139 let db = db.upcast();
140 cairo_lang_debug::helper::HelperDebug::<$long_id, dyn $db>::helper_debug(
141 &db.$lookup(*self),
142 db,
143 )
144 .fmt(f)
145 }
146 }
147 };
148}
149
150pub trait Upcast<T: ?Sized> {
151 fn upcast(&self) -> &T;
152}
153
154impl<T: ?Sized> Upcast<T> for T {
155 fn upcast(&self) -> &T {
156 self
157 }
158}
159
160pub trait UpcastMut<T: ?Sized> {
161 fn upcast_mut(&mut self) -> &mut T;
162}
163
164impl<T: ?Sized> UpcastMut<T> for T {
165 fn upcast_mut(&mut self) -> &mut T {
166 self
167 }
168}
169
170#[must_use = "This function is only relevant to create a possible return."]
177pub fn require(condition: bool) -> Option<()> {
178 condition.then_some(())
179}