use super::*;
impl<E: Environment> Equal<Self> for StringType<E> {
    type Output = Boolean<E>;
    fn is_equal(&self, other: &Self) -> Self::Output {
        let this = self.to_fields();
        let that = other.to_fields();
        self.size_in_bytes.is_equal(&other.size_in_bytes)
            & this.iter().zip(&that).fold(Boolean::constant(true), |acc, (a, b)| acc & a.is_equal(b))
    }
    fn is_not_equal(&self, other: &Self) -> Self::Output {
        !self.is_equal(other)
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    use snarkvm_circuit_environment::Circuit;
    fn sample_string(mode: Mode, rng: &mut TestRng) -> StringType<Circuit> {
        let given = rng.next_string(Circuit::MAX_STRING_BYTES / 4, true);
        StringType::<Circuit>::new(mode, console::StringType::new(&given))
    }
    fn check_is_equal(
        mode: Mode,
        num_constants: u64,
        num_public: u64,
        num_private: u64,
        num_constraints: u64,
    ) -> Result<()> {
        let mut rng = TestRng::default();
        let string_a = sample_string(mode, &mut rng);
        let string_b = sample_string(mode, &mut rng);
        Circuit::scope(format!("{mode}"), || {
            let candidate = string_a.is_equal(&string_a);
            assert!(candidate.eject_value());
            assert_scope!(num_constants, num_public, num_private, num_constraints);
        });
        Circuit::scope(format!("{mode}"), || {
            let candidate = string_a.is_equal(&string_b);
            assert!(!candidate.eject_value());
            assert_scope!(num_constants, num_public, num_private, num_constraints);
        });
        Circuit::reset();
        Ok(())
    }
    fn check_is_not_equal(
        mode: Mode,
        num_constants: u64,
        num_public: u64,
        num_private: u64,
        num_constraints: u64,
    ) -> Result<()> {
        let mut rng = TestRng::default();
        let string_a = sample_string(mode, &mut rng);
        let string_b = sample_string(mode, &mut rng);
        Circuit::scope(format!("{mode}"), || {
            let candidate = string_a.is_not_equal(&string_b);
            assert!(candidate.eject_value());
            assert_scope!(num_constants, num_public, num_private, num_constraints);
        });
        Circuit::scope(format!("{mode}"), || {
            let candidate = string_a.is_not_equal(&string_a);
            assert!(!candidate.eject_value());
            assert_scope!(num_constants, num_public, num_private, num_constraints);
        });
        Circuit::reset();
        Ok(())
    }
    #[test]
    fn test_is_equal_constant() -> Result<()> {
        check_is_equal(Mode::Constant, 9, 0, 0, 0)
    }
    #[test]
    fn test_is_equal_public() -> Result<()> {
        check_is_equal(Mode::Public, 0, 0, 26, 35)
    }
    #[test]
    fn test_is_equal_private() -> Result<()> {
        check_is_equal(Mode::Private, 0, 0, 26, 35)
    }
    #[test]
    fn test_is_not_equal_constant() -> Result<()> {
        check_is_not_equal(Mode::Constant, 9, 0, 0, 0)
    }
    #[test]
    fn test_is_not_equal_public() -> Result<()> {
        check_is_not_equal(Mode::Public, 0, 0, 26, 35)
    }
    #[test]
    fn test_is_not_equal_private() -> Result<()> {
        check_is_not_equal(Mode::Private, 0, 0, 26, 35)
    }
}