use crate::context::{provide_context, use_context};
use base64::{
alphabet,
engine::{self, general_purpose},
Engine,
};
use rand::{rng, RngCore};
use std::{fmt::Display, ops::Deref, sync::Arc};
use tachys::html::attribute::AttributeValue;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Nonce(pub(crate) Arc<str>);
impl Nonce {
pub fn as_inner(&self) -> &Arc<str> {
&self.0
}
}
impl Deref for Nonce {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Display for Nonce {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0)
}
}
impl AttributeValue for Nonce {
type AsyncOutput = Self;
type State = <Arc<str> as AttributeValue>::State;
type Cloneable = Self;
type CloneableOwned = Self;
fn html_len(&self) -> usize {
self.0.len()
}
fn to_html(self, key: &str, buf: &mut String) {
<Arc<str> as AttributeValue>::to_html(self.0, key, buf)
}
fn to_template(_key: &str, _buf: &mut String) {}
fn hydrate<const FROM_SERVER: bool>(
self,
key: &str,
el: &tachys::renderer::types::Element,
) -> Self::State {
<Arc<str> as AttributeValue>::hydrate::<FROM_SERVER>(self.0, key, el)
}
fn build(
self,
el: &tachys::renderer::types::Element,
key: &str,
) -> Self::State {
<Arc<str> as AttributeValue>::build(self.0, el, key)
}
fn rebuild(self, key: &str, state: &mut Self::State) {
<Arc<str> as AttributeValue>::rebuild(self.0, key, state)
}
fn into_cloneable(self) -> Self::Cloneable {
self
}
fn into_cloneable_owned(self) -> Self::CloneableOwned {
self
}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self
}
}
pub fn use_nonce() -> Option<Nonce> {
use_context::<Nonce>()
}
pub fn provide_nonce() {
provide_context(Nonce::new())
}
const NONCE_ENGINE: engine::GeneralPurpose =
engine::GeneralPurpose::new(&alphabet::URL_SAFE, general_purpose::NO_PAD);
impl Nonce {
pub fn new() -> Self {
let mut rng = rng();
let mut bytes = [0; 16];
rng.fill_bytes(&mut bytes);
Nonce(NONCE_ENGINE.encode(bytes).into())
}
}
impl Default for Nonce {
fn default() -> Self {
Self::new()
}
}