1#![forbid(unsafe_code)]
2
3use luct_core::{
4 CtLog, CtLogConfig, SignatureValidationError,
5 tiling::{ParseCheckpointError, TilingError},
6 tree::ProofValidationError,
7};
8use std::{error::Error, fmt::Debug, sync::Arc};
9use thiserror::Error;
10use url::Url;
11
12pub use impls::*;
13
14mod impls;
15mod request;
16mod util;
17
18#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct CtClient<C> {
24 log: CtLog,
25 client: C,
26}
27
28impl<C> CtClient<C> {
29 pub fn new(config: CtLogConfig, client: C) -> Self {
30 Self {
31 log: CtLog::new(config),
32 client,
33 }
34 }
35
36 pub fn log(&self) -> &CtLog {
37 &self.log
38 }
39}
40
41pub trait Client: Debug {
45 fn get(
57 &self,
58 url: &Url,
59 params: &[(&str, &str)],
60 ) -> impl Future<Output = Result<(u16, Arc<String>), ClientError>>;
61
62 fn get_bin(
74 &self,
75 url: &Url,
76 params: &[(&str, &str)],
77 ) -> impl Future<Output = Result<(u16, Arc<Vec<u8>>), ClientError>>;
78
79 }
81
82#[derive(Debug, Clone, Error)]
84pub enum ClientError {
85 #[error("The version of the log is not supported by this client")]
87 UnsupportedVersion,
88
89 #[error("Failed to parse JSON: line: {line}, column: {column}")]
91 JsonError { line: usize, column: usize },
92
93 #[error("Signature validation of {0} against the logs key failed: {1}")]
95 SignatureValidationFailed(&'static str, SignatureValidationError),
96
97 #[error("Failed to validate a consistency path: {0}")]
99 ConsistencyProofError(ProofValidationError),
100
101 #[error("Failed to validate an audit path: {0}")]
103 AuditProofError(ProofValidationError),
104
105 #[error("Failed to connect to host: {0}")]
108 ConnectionError(String),
109
110 #[error("Failed to connect to host: {0}")]
112 ConnectionErrorStd(Arc<dyn Error + Send + Sync>),
113
114 #[error("Request to {url} returned error: {code}: {msg}")]
116 ResponseError { url: String, code: u16, msg: String },
117
118 #[error("Failed parsing checkpoint: {0}")]
120 Checkpoint(#[from] ParseCheckpointError),
121
122 #[error("Tiling error: {0}")]
124 TilingError(#[from] TilingError),
125
126 #[error("The STH could not be parsed")]
129 SthError,
130}
131
132impl From<serde_json::Error> for ClientError {
133 fn from(value: serde_json::Error) -> Self {
134 ClientError::JsonError {
135 line: value.line(),
136 column: value.column(),
137 }
138 }
139}