xspf 0.4.2

straightforward pure rust implementation of the Xml Sharable Playlist Format
Documentation
/// represents an xspf `<playlist>` element.
/// field names are taken from the spec, with the exception of camelCase fields,
/// which have been adjusted to fit the rust naming convention.
#[derive(Default, Debug, Clone)]
#[cfg_attr(feature = "proptest", derive(proptest_derive::Arbitrary))]
#[non_exhaustive]
pub struct Playlist {
	/// A human-readable title for the playlist.
	pub title: Option<String>,
	/// Human-readable name of the entity (author, authors, group, company, etc) that authored the playlist.
	pub creator: Option<String>,
	/// A human-readable comment on the playlist.
	pub annotation: Option<String>,
	/// URI of a web page to find out more about this playlist. Likely to be homepage of the author, and would be used to find out more about the author and to find more playlists by the author.
	pub info: Option<String>,
	/// Source URI for this playlist. xspf:playlist elements MAY contain exactly one.
	/// NOTE: playlists have a single location, but tracks may have multiple.
	pub location: Option<String>,
	/// Canonical ID for this playlist. Likely to be a hash or other location-independent name. MUST be a legal URI. xspf:playlist elements MAY contain exactly one.
	pub identifier: Option<String>,
	/// URI of an image to display in the absence of a //playlist/trackList/image element. xspf:playlist elements MAY contain exactly one.
	pub image: Option<String>,
	/// Creation date (not last-modified date) of the playlist, formatted as a XML schema dateTime. xspf:playlist elements MAY contain exactly one.
	pub date: Option<String>,
	/// URI of a resource that describes the license under which this playlist was released. xspf:playlist elements may contain zero or one license element.
	pub license: Option<String>,
	/// An ordered list of URIs. The purpose is to satisfy licenses allowing modification but requiring attribution.
	/// If you modify such a playlist, move its //playlist/location or //playlist/identifier element to the top of the items in the //playlist/attribution element. (This can be done with the `accredit` method)
	pub attribution: Vec<Attribution>,
	/// The link element allows XSPF to be extended without the use of XML namespaces. xspf:playlist elements MAY contain zero or more link elements.
	pub link: Vec<Meta>,
	/// The meta element allows metadata fields to be added to XSPF. xspf:playlist elements MAY contain zero or more meta elements.
	pub meta: Vec<Meta>,
	/// The extension element allows non-XSPF XML to be included in XSPF documents. The purpose is to allow nested XML, which the meta and link elements do not. xspf:playlist elements MAY contain zero or more extension elements.
    #[cfg_attr(feature = "proptest", proptest(strategy = "proptest::strategy::Just(Vec::<Extension>::new())"))]
	pub extension: Vec<Extension>,
	/// `<trackList>` list of tracks in the playlist.
	pub track_list: Vec<Track>,
}

impl Playlist {
	/// Move the playlist location and/or identifier to the attribution section.
	/// After this operation, both fields are set to None.
	/// `attribution` is then trimmed to 10 elements, as reccomened in the spec
	pub fn accredit(&mut self) {
		// insert the identifier first so the location ends up on top.
		if let Some(id) = self.identifier.take() {
			self.attribution.insert(0, Attribution::Identifier(id));
		}
		if let Some(loc) = self.location.take() {
			self.attribution.insert(0, Attribution::Location(loc));
		}
		self.attribution.truncate(10);
	}
}

#[non_exhaustive]
#[derive(Default, Debug, Clone)]
#[cfg_attr(feature = "proptest", derive(proptest_derive::Arbitrary))]
pub struct Track {
	/// URI of resource to be rendered. Probably an audio resource, but MAY be any type of resource with a well-known duration, such as video, a SMIL document, or an XSPF document. The duration of the resource defined in this element defines the duration of rendering. xspf:track elements MAY contain zero or more location elements, but a user-agent MUST NOT render more than one of the named resources.
	pub location: Vec<String>,
	/// Canonical ID for this resource. Likely to be a hash or other location-independent name, such as a `MusicBrainz` identifier.
	pub identifier: Vec<String>,
	/// Human-readable name of the track that authored the resource which defines the duration of track rendering. This value is primarily for fuzzy lookups, though a user-agent may display it. xspf:track elements MAY contain exactly one.
	pub title: Option<String>,
	/// Human-readable name of the entity (author, authors, group, company, etc) that authored the resource which defines the duration of track rendering. This value is primarily for fuzzy lookups, though a user-agent may display it. xspf:track elements MAY contain exactly one.
	pub creator: Option<String>,
	/// A human-readable comment on the track. This is character data, not HTML, and it may not contain markup. xspf:track elements MAY contain exactly one.
	pub annotation: Option<String>,
	/// URI of a place where this resource can be bought or more info can be found. xspf:track elements MAY contain exactly one.
	pub info: Option<String>,
	/// URI of an image to display for the duration of the track. xspf:track elements MAY contain exactly one.
	pub image: Option<String>,
	/// Human-readable name of the collection from which the resource which defines the duration of track rendering comes. For a song originally published as a part of a CD or LP, this would be the title of the original release. This value is primarily for fuzzy lookups, though a user-agent may display it. xspf:track elements MAY contain exactly one.
	pub album: Option<String>,
	/// Integer with value greater than zero giving the ordinal position of the media on the xspf:album. This value is primarily for fuzzy lookups, though a user-agent may display it.
	pub track_num: Option<u64>,
	/// The time to render a resource, in milliseconds. It MUST be a valid XML Schema nonNegativeInteger. This value is only a hint — different XSPF generators will generate slightly different values. A user-agent MUST NOT use this value to determine the rendering duration, since the data will likely be low quality. xspf:track elements MAY contain exactly one duration element.
	pub duration: Option<u64>,
	/// The link element allows XSPF to be extended without the use of XML namespaces. xspf:track elements MAY contain zero or more link elements.
	pub link: Vec<Meta>,
	/// The meta element allows metadata fields to be added to xspf:track elements. xspf:track elements MAY contain zero or more meta elements.
	pub meta: Vec<Meta>,
	/// The extension element allows non-XSPF XML to be included in XSPF documents. The purpose is to allow nested XML, which the meta and link elements do not. xspf:track elements MAY contain zero or more extension elements.
    #[cfg_attr(feature = "proptest", proptest(strategy = "proptest::strategy::Just(Vec::<Extension>::new())"))]
	pub extension: Vec<Extension>,
}

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "proptest", derive(proptest_derive::Arbitrary))]
pub enum Attribution {
	Location(String),
	Identifier(String),
}

/// datatype used for ref fields like `<link>` and `<meta>`
#[derive(Debug, Clone)]
#[cfg_attr(feature = "proptest", derive(proptest_derive::Arbitrary))]
pub struct Meta {
	/// value of the rel attribute.  is a URI.
	pub rel: String,
	/// value contained by the element.
	/// for `<meta>` tags, this is text,
	/// for `<link>` tags, this is a URI
	pub content: String,
}

/// datatype used for `<extension>`
#[derive(Debug, Clone)]
pub struct Extension {
	/// snapshot of the namespace context at the start of the tag.
	/// exists so you can declare an xml namespace at the start of a playlist,
	/// then use it in extension tags.
	pub namespace: xml::namespace::Namespace,
	/// URI of a resource defining the structure and purpose of the nested XML.
	pub application: String,
	/// xml events contained in the `<extension>` tag
	pub content: Vec<xml::reader::XmlEvent>,
}