media-codec 0.9.1

A generic framework for encoding and decoding
Documentation
use std::{
    collections::HashMap,
    marker::PhantomData,
    sync::{Arc, LazyLock, RwLock},
};

use media_codec_types::{CodecBuilder, CodecID, CodecSpec};
use media_core::{invalid_error, not_found_error, Result};

pub(crate) struct CodecList<S: CodecSpec, B: ?Sized + CodecBuilder<S> = dyn CodecBuilder<S>> {
    pub(crate) codecs: HashMap<CodecID, Vec<Arc<B>>>,
    pub(crate) _marker: PhantomData<S>,
}

pub(crate) type LazyCodecList<S, B = dyn CodecBuilder<S>> = LazyLock<RwLock<CodecList<S, B>>>;

pub(crate) fn register_codec<S, B>(codec_list: &LazyCodecList<S, B>, builder: Arc<B>, default: bool) -> Result<()>
where
    S: CodecSpec,
    B: ?Sized + CodecBuilder<S>,
{
    let mut codec_list = codec_list.write().map_err(|err| invalid_error!(err.to_string()))?;
    for &id in builder.ids() {
        let list = codec_list.codecs.entry(id).or_default();

        if default {
            list.insert(0, builder.clone());
        } else {
            list.push(builder.clone());
        }
    }

    Ok(())
}

pub(crate) fn find_codec<S, B>(codec_list: &LazyCodecList<S, B>, id: CodecID) -> Result<Arc<B>>
where
    S: CodecSpec,
    B: ?Sized + CodecBuilder<S>,
{
    let codec_list = codec_list.read().map_err(|err| invalid_error!(err.to_string()))?;

    if let Some(builders) = codec_list.codecs.get(&id) {
        if let Some(builder) = builders.first() {
            return Ok(builder.clone());
        }
    }

    Err(not_found_error!(format!("codec: {:?}", id)))
}

pub(crate) fn find_codec_by_name<S, B>(codec_list: &LazyCodecList<S, B>, name: &str) -> Result<Arc<B>>
where
    S: CodecSpec,
    B: ?Sized + CodecBuilder<S>,
{
    let codec_list = codec_list.read().map_err(|err| invalid_error!(err.to_string()))?;

    for builders in codec_list.codecs.values() {
        for builder in builders {
            if builder.name() == name {
                return Ok(builder.clone());
            }
        }
    }

    Err(not_found_error!(format!("codec: {}", name)))
}