Skip to main content

arminius_lib_model/
types.rs

1// SPDX-FileCopyrightText: 2025 BWI GmbH
2//
3// SPDX-License-Identifier: Apache-2.0
4
5//! General types definition.
6//!
7//! Contains conversion from rust to `sqlx` (PostgreSQL) types.
8
9use std::error::Error;
10
11use sqlx::{
12	Decode, Encode, Postgres,
13	encode::IsNull,
14	postgres::{PgArgumentBuffer, PgTypeInfo, PgValueRef},
15	prelude::Type,
16};
17use ulid::Ulid;
18
19/// Index into the event stream. See <https://bundesmessenger.gitlab.io/backend/neo/arminius/arminius/architecture/sync.html>
20pub type StreamId = i64;
21
22/// Wrapper type containing the PostgreSQL UUID type.
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub struct DbUlid(pub Ulid);
25
26impl Type<Postgres> for DbUlid {
27	fn type_info() -> PgTypeInfo {
28		PgTypeInfo::with_name("uuid")
29	}
30}
31
32impl<'r> Decode<'r, Postgres> for DbUlid {
33	fn decode(value: PgValueRef<'r>) -> Result<Self, Box<dyn Error + 'static + Send + Sync>> {
34		let bytes = value.as_bytes()?;
35
36		if bytes.len() != 16 {
37			return Err("Invalid UUID length from database, expected 16 bytes".into());
38		}
39
40		let mut arr = [0_u8; 16];
41		arr.copy_from_slice(bytes);
42
43		Ok(DbUlid(Ulid::from_bytes(arr)))
44	}
45}
46
47impl<'q> Encode<'q, Postgres> for DbUlid {
48	fn encode_by_ref(
49		&self,
50		buf: &mut PgArgumentBuffer,
51	) -> Result<IsNull, Box<dyn Error + Send + Sync>> {
52		buf.extend_from_slice(&self.0.to_bytes());
53
54		Ok(IsNull::No)
55	}
56}