Allow lua to be able to get and modify any field
This commit is contained in:
parent
fc8dd690c1
commit
49c47ebfd7
|
|
@ -10,8 +10,48 @@ function get(url) end
|
|||
--- @param xml string
|
||||
function parse_xml_feed(xml) end
|
||||
|
||||
--- @class HtmlParser
|
||||
HtmlParser = {}
|
||||
|
||||
--- @param html string
|
||||
function HtmlParser:parse(html) end
|
||||
|
||||
--- @class Feed
|
||||
--- @field channel Channel
|
||||
Feed = {}
|
||||
|
||||
--- @return Feed
|
||||
--- @param xml string
|
||||
--- @return Feed
|
||||
function Feed:new(xml) end
|
||||
|
||||
--- @return string
|
||||
function Feed:render() end
|
||||
|
||||
--- @class Channel
|
||||
--- @field title string
|
||||
--- @field atom_link AtomLink
|
||||
--- @field articles Article[]
|
||||
Channel = {}
|
||||
|
||||
--- @class Article
|
||||
--- @field title string
|
||||
--- @field link string
|
||||
--- @field creator string
|
||||
--- @field pub_date string
|
||||
--- @field categories string[]
|
||||
--- @field guid Guid
|
||||
--- @field description string
|
||||
Article = {}
|
||||
|
||||
--- @class AtomLink
|
||||
--- @field href string
|
||||
--- @field rel string
|
||||
--- @field type string
|
||||
AtomLink = {}
|
||||
|
||||
--- @class Guid
|
||||
--- @field is_perma_link boolean
|
||||
--- @field guid string
|
||||
Guid = {}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,16 +4,18 @@ local feed = rss_parser:new(xml)
|
|||
local channel = feed.channel
|
||||
log:info("Title: " .. channel.title)
|
||||
|
||||
feed.channel.title = "Really Working Title"
|
||||
|
||||
-- local atom_link = AtomLink()
|
||||
-- atom_link.href = "http://localhost:8081/feed.xml"
|
||||
-- atom_link.rel = "self"
|
||||
-- atom_link.mime_type = "application/rss+xml"
|
||||
--
|
||||
-- print(feed:render())
|
||||
-- feed.channel.title = "New Title"
|
||||
feed.channel.title = "Really Working Title"
|
||||
feed.channel.atom_link.href = "http://localhost:8081/feed.xml"
|
||||
feed.channel.articles[1].title = "New Article Title"
|
||||
feed.channel.articles[2].title = "New Article Title 2"
|
||||
|
||||
print(feed.channel.articles[1].description)
|
||||
feed.channel.articles[1].description = "New Description"
|
||||
|
||||
print(feed:render())
|
||||
-- feed.channel.title = "New Title"
|
||||
-- print(feed:render())
|
||||
|
||||
-- NOTE: HTML Parser
|
||||
-- local article = get("http://localhost:8081")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use log::debug;
|
||||
use mlua::{
|
||||
AnyUserDataExt, FromLua, Lua, Result, Table, UserData, UserDataFields, UserDataMethods, Value,
|
||||
AnyUserDataExt, FromLua, IntoLua, Lua, Result, Table, UserData, UserDataFields,
|
||||
UserDataMethods, Value,
|
||||
};
|
||||
use quick_xml::de::from_str;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
@ -15,6 +17,12 @@ macro_rules! add_field_method_get {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! add_field_method_get_mut {
|
||||
($fields:ident, $name:literal, $field:ident) => {
|
||||
$fields.add_field_method_get($name, |_, this| Ok(this.$field));
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! add_field_method_set {
|
||||
($fields:ident, $name:literal, $field:ident, $type:ty) => {
|
||||
$fields.add_field_method_set($name, |_, this, value: $type| {
|
||||
|
|
@ -53,6 +61,15 @@ macro_rules! add_field_method_get_set_rc {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! add_field_method_set_rc_option {
|
||||
($fields:ident, $name:literal, $field:ident, $type:ty) => {
|
||||
$fields.add_field_method_set($name, |_, this, value: Option<$type>| {
|
||||
this.$field = value.map(|v| Rc::new(RefCell::new(v)));
|
||||
Ok(())
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! implement_from_lua {
|
||||
($type:ty) => {
|
||||
impl FromLua<'_> for $type {
|
||||
|
|
@ -66,6 +83,7 @@ macro_rules! implement_from_lua {
|
|||
};
|
||||
}
|
||||
|
||||
/// Lua object representing an RSS feed as Feed
|
||||
#[derive(Default, Debug, Deserialize, Serialize, Clone)]
|
||||
#[serde(rename = "rss")]
|
||||
pub struct Rss {
|
||||
|
|
@ -73,14 +91,23 @@ pub struct Rss {
|
|||
channel: Rc<RefCell<Channel>>,
|
||||
}
|
||||
|
||||
type SharedOptionImage = Rc<RefCell<Option<Image>>>;
|
||||
type SharedRcItem = Rc<RefCell<Item>>;
|
||||
implement_from_lua!(Rss);
|
||||
impl UserData for Rss {
|
||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
add_field_method_get_set_rc!(fields, "channel", channel, Channel);
|
||||
}
|
||||
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_method("new", |_, _, xml: String| Ok(Rss::new(&xml)));
|
||||
methods.add_method("render", |_, this, ()| Ok(this.render()));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct Channel {
|
||||
title: Option<String>,
|
||||
#[serde(rename = "atom_link")]
|
||||
atom_link: Option<AtomLink>,
|
||||
atom_link: Option<Rc<RefCell<AtomLink>>>,
|
||||
#[serde(rename = "link")]
|
||||
link: Option<String>,
|
||||
description: Option<String>,
|
||||
|
|
@ -92,16 +119,17 @@ pub struct Channel {
|
|||
#[serde(rename = "sy:updateFrequency")]
|
||||
update_frequency: Option<String>,
|
||||
generator: Option<String>,
|
||||
image: Option<Image>,
|
||||
image: Option<Rc<RefCell<Image>>>,
|
||||
#[serde(rename = "item", default)]
|
||||
items: Vec<Item>,
|
||||
items: Vec<Rc<RefCell<Item>>>,
|
||||
}
|
||||
|
||||
implement_from_lua!(Channel);
|
||||
impl UserData for Channel {
|
||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
add_field_method_get_set!(fields, "title", title, Option<String>);
|
||||
add_field_method_get_set!(fields, "atom_link", atom_link, Option<AtomLink>);
|
||||
add_field_method_get_rc!(fields, "atom_link", atom_link);
|
||||
add_field_method_set_rc_option!(fields, "atom_link", atom_link, AtomLink);
|
||||
add_field_method_get_set!(fields, "link", link, Option<String>);
|
||||
add_field_method_get_set!(fields, "description", description, Option<String>);
|
||||
add_field_method_get_set!(fields, "last_build_date", last_build_date, Option<String>);
|
||||
|
|
@ -110,9 +138,24 @@ impl UserData for Channel {
|
|||
add_field_method_get_set!(fields, "update_frequency", update_frequency, Option<String>);
|
||||
add_field_method_get_set!(fields, "generator", generator, Option<String>);
|
||||
|
||||
// TODO: Implement shared reference for image and item
|
||||
add_field_method_get_set!(fields, "image", image, Option<Image>);
|
||||
add_field_method_get_set!(fields, "items", items, Vec<Item>);
|
||||
add_field_method_get_rc!(fields, "image", image);
|
||||
add_field_method_set_rc_option!(fields, "image", image, Image);
|
||||
add_field_method_get_rc!(fields, "articles", items);
|
||||
fields.add_field_method_set("articles", |_, this, items: Vec<Item>| {
|
||||
this.items = items
|
||||
.into_iter()
|
||||
.map(|i| Rc::new(RefCell::new(i)))
|
||||
.collect();
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_method("new", |_, _, ()| Ok(Channel::default()));
|
||||
methods.add_method_mut("add_item", |_, this, item: Item| {
|
||||
this.items.push(Rc::new(RefCell::new(item)));
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,14 +167,7 @@ pub struct AtomLink {
|
|||
mime_type: Option<String>,
|
||||
}
|
||||
|
||||
impl FromLua<'_> for AtomLink {
|
||||
fn from_lua(value: Value, _: &Lua) -> Result<Self> {
|
||||
match value {
|
||||
Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
implement_from_lua!(AtomLink);
|
||||
|
||||
impl UserData for AtomLink {
|
||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
|
|
@ -145,7 +181,6 @@ impl UserData for AtomLink {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Default, Debug, Deserialize, Serialize, Clone)]
|
||||
struct Image {
|
||||
url: Option<String>, // Option for missing fields
|
||||
|
|
@ -170,8 +205,9 @@ impl UserData for Image {
|
|||
}
|
||||
}
|
||||
|
||||
/// Lua object representing an RSS item as Article
|
||||
#[derive(Default, Debug, Deserialize, Serialize, Clone)]
|
||||
struct Item {
|
||||
pub struct Item {
|
||||
title: Option<String>, // Marked Option
|
||||
link: Option<String>,
|
||||
#[serde(rename = "dc:creator")]
|
||||
|
|
@ -235,14 +271,3 @@ impl Rss {
|
|||
}
|
||||
}
|
||||
|
||||
implement_from_lua!(Rss);
|
||||
impl UserData for Rss {
|
||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
add_field_method_get_set_rc!(fields, "channel", channel, Channel);
|
||||
}
|
||||
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_method("new", |_, _, xml: String| Ok(Rss::new(&xml)));
|
||||
methods.add_method("render", |_, this, ()| Ok(this.render()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{html_parser::HtmlParser, rss_parser::AtomLink};
|
||||
use crate::router;
|
||||
use crate::rss_parser::{Channel, Rss};
|
||||
use crate::rss_parser::{Channel, Item, Rss};
|
||||
use log::{debug, error, info, warn};
|
||||
use mlua::{Lua, MetaMethod, Result, UserData, UserDataMethods};
|
||||
use std::{
|
||||
|
|
@ -82,9 +82,9 @@ impl Scripting {
|
|||
|
||||
add_constructor!("HtmlParser", HtmlParser);
|
||||
add_constructor!("Feed", Rss);
|
||||
|
||||
add_constructor!("Channel", Channel);
|
||||
add_constructor!("AtomLink", AtomLink);
|
||||
add_constructor!("Article", Item);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue