qfall_math/integer_mod_q/z_q/to_string.rs
1// Copyright © 2023 Marcel Luca Schmidt, Niklas Siemer
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! This module contains all options to convert an integer of type
10//! [`Zq`] into a [`String`].
11//!
12//! This includes the [`Display`](std::fmt::Display) trait.
13
14use super::Zq;
15use crate::macros::for_others::implement_for_owned;
16use core::fmt;
17use std::string::FromUtf8Error;
18
19impl From<&Zq> for String {
20 /// Converts a [`Zq`] into its [`String`] representation.
21 ///
22 /// Parameters:
23 /// - `value`: specifies the integer and modulus that will be represented as a [`String`]
24 ///
25 /// Returns a [`String`] of the form `"x mod q"`.
26 ///
27 /// # Examples
28 /// ```
29 /// use qfall_math::integer_mod_q::Zq;
30 /// use std::str::FromStr;
31 /// let zq = Zq::from_str("3 mod 5").unwrap();
32 ///
33 /// let string: String = zq.into();
34 /// ```
35 fn from(value: &Zq) -> Self {
36 value.to_string()
37 }
38}
39
40implement_for_owned!(Zq, String, From);
41
42impl fmt::Display for Zq {
43 /// Allows to convert an integer of type [`Zq`] into a [`String`].
44 ///
45 /// Returns the integer in form of a [`String`]. For integer `2 mod 4`
46 /// the String looks like this `2 mod 4`.
47 ///
48 /// # Examples
49 /// ```
50 /// use qfall_math::integer_mod_q::Zq;
51 /// use std::str::FromStr;
52 /// use core::fmt;
53 ///
54 /// let integer_mod_q = Zq::from((42, 3));
55 /// println!("{integer_mod_q}");
56 /// ```
57 ///
58 /// ```
59 /// use qfall_math::integer_mod_q::Zq;
60 /// use std::str::FromStr;
61 /// use core::fmt;
62 ///
63 /// let integer_mod_q = Zq::from((42, 3));
64 /// let integer_string = integer_mod_q.to_string();
65 /// ```
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 write!(f, "{} mod {}", self.value, self.modulus)
68 }
69}
70
71impl Zq {
72 /// Enables conversion to a UTF8-Encoded [`String`] for [`Zq`] values.
73 /// The inverse to this function is [`Zq::from_utf8`] for valid UTF8-Encodings.
74 ///
75 /// **Warning**: Not every byte-sequence forms a valid UTF8-character.
76 /// If this is the case, a [`FromUtf8Error`] will be returned.
77 ///
78 /// Returns the corresponding UTF8-encoded [`String`] or a
79 /// [`FromUtf8Error`] if the byte sequence contains an invalid UTF8-character.
80 ///
81 /// # Examples
82 /// ```
83 /// use qfall_math::integer_mod_q::Zq;
84 /// let value = Zq::from((10, 63));
85 ///
86 /// let text: String = value.to_utf8().unwrap();
87 /// ```
88 ///
89 /// # Errors and Failures
90 /// - Returns a [`FromUtf8Error`] if the integer's byte sequence contains
91 /// valid UTF8-characters.
92 pub fn to_utf8(&self) -> Result<String, FromUtf8Error> {
93 String::from_utf8(
94 self.get_representative_least_nonnegative_residue()
95 .to_bytes(),
96 )
97 }
98}
99
100#[cfg(test)]
101mod test_to_string {
102 use crate::integer_mod_q::Zq;
103 use std::str::FromStr;
104
105 /// Tests whether a large integer works in a roundtrip
106 #[test]
107 fn working_large_positive() {
108 let cmp = Zq::from_str(&format!("{} mod {}", u64::MAX, u128::MAX)).unwrap();
109
110 assert_eq!(format!("{} mod {}", u64::MAX, u128::MAX), cmp.to_string());
111 }
112
113 /// Tests whether a large integer works in a roundtrip
114 #[test]
115 fn working_large_negative() {
116 let cmp = Zq::from_str(&format!("-{} mod {}", u64::MAX, u128::MAX)).unwrap();
117 let diff = u128::MAX - u64::MAX as u128;
118
119 assert_eq!(format!("{diff} mod {}", u128::MAX), cmp.to_string());
120 }
121
122 /// Tests whether a positive integer works in a roundtrip
123 #[test]
124 fn working_positive() {
125 let cmp = Zq::from_str("42 mod 60").unwrap();
126
127 assert_eq!("42 mod 60", cmp.to_string());
128 }
129
130 /// Tests whether a negative integer works in a roundtrip
131 #[test]
132 fn working_negative() {
133 let cmp = Zq::from_str("-40 mod 3").unwrap();
134
135 assert_eq!("2 mod 3", cmp.to_string());
136 }
137
138 /// Tests whether a integer that is created using a string, returns a
139 /// string that can be used to create a [`Zq`]
140 #[test]
141 fn working_use_result_of_to_string_as_input() {
142 let cmp = Zq::from((42, 10));
143
144 let cmp_str = cmp.to_string();
145
146 assert!(Zq::from_str(&cmp_str).is_ok());
147 }
148
149 /// Ensures that the `Into<String>` trait works properly
150 #[test]
151 fn into_works_properly() {
152 let cmp = "6 mod 11";
153 let zq = Zq::from_str(cmp).unwrap();
154
155 let string: String = zq.clone().into();
156 let borrowed_string: String = (&zq).into();
157
158 assert_eq!(cmp, string);
159 assert_eq!(cmp, borrowed_string);
160 }
161}
162
163#[cfg(test)]
164/// This module omits tests performed in [`crate::integer::Z::to_utf8`].
165mod test_to_utf8 {
166 use super::Zq;
167
168 /// Ensures that [`Zq::to_utf8`] is inverse to [`Zq::from_utf8`] for valid UTF8-Encodings.
169 #[test]
170 fn inverse_to_from_utf8() {
171 let cmp_text = "Test!";
172
173 let value = Zq::from_utf8(cmp_text, u64::MAX).unwrap();
174 let text = value.to_utf8().unwrap();
175
176 assert_eq!(cmp_text, text);
177 }
178}