#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/mccs/0.2.0")]
use std::{
collections::{btree_map, BTreeMap},
convert::Infallible,
fmt::{self, Display, Formatter},
str::FromStr,
};
pub type FeatureCode = u8;
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Value {
pub ty: u8,
pub mh: u8,
pub ml: u8,
pub sh: u8,
pub sl: u8,
}
#[repr(u8)]
pub enum ValueType {
SetParameter = 0,
Momentary = 1,
}
impl Value {
pub fn from_value(v: u16) -> Self {
Value {
sh: (v >> 8) as u8,
sl: v as u8,
..Default::default()
}
}
pub fn value(&self) -> u16 {
((self.sh as u16) << 8) | self.sl as u16
}
pub fn maximum(&self) -> u16 {
((self.mh as u16) << 8) | self.ml as u16
}
pub fn ty(&self) -> Result<ValueType, u8> {
match self.ty {
0 => Ok(ValueType::SetParameter),
1 => Ok(ValueType::Momentary),
ty => Err(ty),
}
}
}
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Value")
.field("maximum", &self.maximum())
.field("value", &self.value())
.field("ty", &self.ty)
.finish()
}
}
pub type EdidData = Vec<u8>;
pub type VdifData = Vec<u8>;
pub type ValueNames = BTreeMap<u8, Option<String>>;
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Capabilities {
pub protocol: Option<Protocol>,
pub ty: Option<Type>,
pub model: Option<String>,
pub commands: Vec<u8>,
pub ms_whql: Option<u8>,
pub mccs_version: Option<Version>,
pub vcp_features: BTreeMap<FeatureCode, VcpDescriptor>,
pub edid: Option<EdidData>,
pub vdif: Vec<VdifData>,
pub unknown_tags: Vec<UnknownTag>,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Protocol {
Monitor,
Display,
Unknown(String),
}
impl<'a> From<&'a str> for Protocol {
fn from(s: &'a str) -> Self {
match s {
"monitor" => Protocol::Monitor,
"display" => Protocol::Display,
s => Protocol::Unknown(s.into()),
}
}
}
impl Display for Protocol {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Display::fmt(
match *self {
Protocol::Monitor => "monitor",
Protocol::Display => "display",
Protocol::Unknown(ref s) => s,
},
f,
)
}
}
impl FromStr for Protocol {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(s.into())
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Type {
Crt,
Lcd,
Led,
Unknown(String),
}
impl<'a> From<&'a str> for Type {
fn from(s: &'a str) -> Self {
match s {
s if s.eq_ignore_ascii_case("crt") => Type::Crt,
s if s.eq_ignore_ascii_case("lcd") => Type::Lcd,
s if s.eq_ignore_ascii_case("led") => Type::Led,
s => Type::Unknown(s.into()),
}
}
}
impl Display for Type {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Display::fmt(
match *self {
Type::Crt => "crt",
Type::Lcd => "lcd",
Type::Led => "led",
Type::Unknown(ref s) => s,
},
f,
)
}
}
impl FromStr for Type {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(s.into())
}
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Version {
pub major: u8,
pub minor: u8,
}
impl Version {
pub fn new(major: u8, minor: u8) -> Self {
Version { major, minor }
}
}
impl Display for Version {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}.{}", self.major, self.minor)
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VcpDescriptor {
pub name: Option<String>,
pub values: ValueNames,
}
impl VcpDescriptor {
pub fn values(&self) -> btree_map::Keys<u8, Option<String>> {
self.values.keys()
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UnknownTag {
pub name: String,
pub data: UnknownData,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum UnknownData {
String(String),
StringBytes(Vec<u8>),
Binary(Vec<u8>),
}