aboutsummaryrefslogblamecommitdiffstats
path: root/src/error.rs
blob: 26b7766854ae26421d003499dc1d334824778eb1 (plain) (tree)
1
2
3
4
5
6
7
8
9
10


                                     
                   
              
  
 
                     

                              
 



                                                   
 
                                                                                      
                              
                           
                               
                                                               
                    
                              
                                           
                                                
                                   
                                                 
                                         
                          
                                         
                           
                                        

                                                                               
                                        

                                                                               
                                                                 

                                                              
                                       
                                              
                 
                                            
                                                   
                 
                                                                                     
                           

                                         
                                     

                                                  
                     

                            

 
                                                  
                                               
                              
                


                                  



                                    
                                 
                                
                               
                                                    
                               
                                                

                                                      
                                                        
                                        
                               
                                                                   
                                 
                                            
                         
                                                                       
                      
                                                                
                                
                                          
                                          
                                                             
                     




                                      
                             


                              
                              

                     
                         

                                
                          

                                 
                          





                                 
                                  
                                              
     

 





                                        
                                     
                              
                       
                    
                                
                                    
                                    

                                                         
                                         

                                             
 
use std::{
    collections::{HashMap, VecDeque},
    num::ParseIntError,
    str::Utf8Error,
    sync::Arc,
};

use thiserror::Error;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::JsValue;

use crate::{
    element::{Content, Name, NamespaceDeclaration},
    Element,
};

/// Error type for the `FromElement` trait. Used when deserialising from an `Element`.
#[derive(Error, Debug, Clone)]
pub enum DeserializeError {
    /// Could not parse string.
    #[error("could not parse string {0:?} to requested value")]
    FromStr(String),
    /// Unexpected attributes.
    #[error("unexpected attributes {0:?}")]
    UnexpectedAttributes(HashMap<Name, String>),
    /// Unexpected element content.
    #[error("unexpected element content: {0:?}")]
    UnexpectedContent(VecDeque<Content>),
    /// Missing attribute.
    #[error("attribute `{0:?}` missing")]
    MissingAttribute(Name),
    /// Incorrect localname encountered.
    #[error("incorrect localname: expected `{expected:?}`, found `{found:?}`")]
    IncorrectName { expected: String, found: String },
    /// Incorrect namespace encountered.
    #[error("incorrect namespace: expected `{expected:?}`, found `{found:?}`")]
    IncorrectNamespace { expected: String, found: String },
    /// Unqualified namespace when expecting qualified namespace.
    #[error("unqualified namespace: expected `{expected:?}`")]
    Unqualified { expected: String },
    /// Element missing expected child.
    #[error("element missing expected child")]
    MissingChild,
    /// Element missing expected text value.
    #[error("element missing expected text value")]
    MissingValue,
    // not used by crate (yet), but may be used by consumers implementing FromElement
    /// Unexpected element.
    #[error("unexpected element: {0:?}")]
    UnexpectedElement(Element),
    /// Attribute is an empty string.
    #[error("attribute `{0}` is an empty string")]
    AttributeEmptyString(String),
    /// Empty string.
    #[error("empty string")]
    EmptyString,
}

/// General error type for functions in the crate.
// TODO: add error context (usually the stanza)
#[derive(Error, Debug, Clone)]
pub enum Error {
    #[cfg(target_arch = "wasm32")]
    #[error("websocket closed")]
    WebSocketClosed,
    #[error("io: {0}")]
    // TODO: is this okay?
    ReadError(Arc<std::io::Error>),
    #[error("utf8 conversion: {0}")]
    Utf8Error(#[from] Utf8Error),
    #[error("nom parsing: {0}")]
    ParseError(String, String),
    #[error("unknown xml entity reference `&{0};`")]
    EntityProcessError(String),
    #[error("invalid character reference: {0}")]
    InvalidCharRef(CharRefError),
    #[error("duplicate namespace declaration: {0:?}")]
    DuplicateNameSpaceDeclaration(NamespaceDeclaration),
    #[error("duplicate attribute: {0}")]
    DuplicateAttribute(String),
    #[error("mismatched end tag: expected `{0:?}`, found `{1:?}`")]
    MismatchedEndTag(Name, Name),
    #[error("not currently in any element")]
    NotInElement(String),
    #[error("extra unexpected data included in complete parse: `{0}`")]
    ExtraData(String),
    #[error("namespace `{0}` has not previously been declared")]
    UndeclaredNamespace(String),
    #[error("deserialization error: {0}")]
    Deserialize(#[from] DeserializeError),
    #[error("root element has already been fully processed")]
    RootElementEnded,
    #[cfg(target_arch = "wasm32")]
    #[error("websocket error: {0}")]
    Websocket(#[from] WebsocketError),
}

/// Websocket-related errors.
#[cfg(target_arch = "wasm32")]
#[derive(Error, Debug, Clone)]
pub enum WebsocketError {
    /// Websocket write error.
    #[error("write")]
    Write,
    /// Invalid encoding.
    #[error("invalid encoding")]
    InvalidEncoding,
    /// Can't decode blob.
    #[error("can't decode blob")]
    CantDecodeBlob,
    /// Unknown data type.
    #[error("unknown data type")]
    UnknownDataType,
}

#[cfg(target_arch = "wasm32")]
impl From<JsValue> for Error {
    fn from(_e: JsValue) -> Self {
        Self::Websocket(WebsocketError::Write)
    }
}

impl From<std::io::Error> for Error {
    fn from(e: std::io::Error) -> Self {
        Self::ReadError(Arc::new(e))
    }
}

/// Character reference decode error.
#[derive(Error, Debug, Clone)]
pub enum CharRefError {
    /// Int parsing.
    #[error("int parsing: {0}")]
    ParseInt(#[from] ParseIntError),
    /// Integer is not a valid char.
    #[error("u32 `{0}` does not represent a valid char")]
    IntegerNotAChar(u32),
    /// Character is an invalid XML char.
    #[error("`{0}` is not a valid xml char")]
    InvalidXMLChar(char),
}