reifydb-type 0.4.11

Core type system and value representations for ReifyDB
Documentation
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2025 ReifyDB

use super::Blob;
use crate::{
	error::{BlobEncodingKind, Error, TypeError},
	fragment::Fragment,
};

impl Blob {
	pub fn from_utf8(fragment: Fragment) -> Self {
		let utf8_str = fragment.text();
		Blob::new(utf8_str.as_bytes().to_vec())
	}

	pub fn to_utf8(&self) -> Result<String, Error> {
		match str::from_utf8(self.as_bytes()) {
			Ok(s) => Ok(s.to_string()),
			Err(e) => Err(TypeError::BlobEncoding {
				kind: BlobEncodingKind::InvalidUtf8Sequence {
					error: e.to_string(),
				},
				message: format!("Invalid UTF-8 sequence in BLOB: {}", e),
				fragment: Fragment::internal(e.to_string()),
			}
			.into()),
		}
	}

	pub fn to_utf8_lossy(&self) -> String {
		String::from_utf8_lossy(self.as_bytes()).to_string()
	}

	#[allow(clippy::should_implement_trait)]
	pub fn from_str(fragment: Fragment) -> Self {
		Self::from_utf8(fragment)
	}
}

#[cfg(test)]
pub mod tests {
	use super::*;
	use crate::fragment::Fragment;

	#[test]
	fn test_from_utf8() {
		let blob = Blob::from_utf8(Fragment::testing("Hello, World!"));
		assert_eq!(blob.as_bytes(), b"Hello, World!");
	}

	#[test]
	fn test_from_utf8_unicode() {
		let blob = Blob::from_utf8(Fragment::testing("Hello, δΈ–η•Œ! πŸ¦€"));
		assert_eq!(blob.as_bytes(), "Hello, δΈ–η•Œ! πŸ¦€".as_bytes());
	}

	#[test]
	fn test_from_utf8_empty() {
		let blob = Blob::from_utf8(Fragment::testing(""));
		assert_eq!(blob.as_bytes(), b"");
	}

	#[test]
	fn test_to_utf8() {
		let blob = Blob::new("Hello, δΈ–η•Œ!".as_bytes().to_vec());
		assert_eq!(blob.to_utf8().unwrap(), "Hello, δΈ–η•Œ!");
	}

	#[test]
	fn test_to_utf8_invalid() {
		let blob = Blob::new(vec![0xFF, 0xFE]);
		assert!(blob.to_utf8().is_err());
	}

	#[test]
	fn test_to_utf8_lossy() {
		let blob = Blob::new("Hello, δΈ–η•Œ!".as_bytes().to_vec());
		assert_eq!(blob.to_utf8_lossy(), "Hello, δΈ–η•Œ!");

		let invalid_blob = Blob::new(vec![0xFF, 0xFE]);
		let lossy = invalid_blob.to_utf8_lossy();
		assert!(lossy.contains('οΏ½')); // replacement character
	}

	#[test]
	fn test_from_str() {
		let blob = Blob::from_str(Fragment::testing("Hello!"));
		assert_eq!(blob.as_bytes(), b"Hello!");
	}

	#[test]
	fn test_utf8_roundtrip() {
		let original = "Hello, δΈ–η•Œ! πŸ¦€ Test with emojis and unicode";
		let blob = Blob::from_utf8(Fragment::testing(original));
		let decoded = blob.to_utf8().unwrap();
		assert_eq!(decoded, original);
	}
}