parsav  store.t at [25e05466d5]

File store.t artifact 2c2e954f5c part of check-in 25e05466d5


-- vim: ft=terra
local m = {
	timepoint = uint64;
	scope = lib.enum {
		'public', 'private', 'local';
		'personal', 'direct', 'circle';
	};
	notiftype = lib.enum {
		'mention', 'like', 'rt', 'react'
	};
	relation = lib.enum {
		'follow', 'mute', 'block'
	};
	credset = lib.set {
		'pw', 'otp', 'challenge', 'trust'
	};
}

local str = rawstring --lib.mem.ptr(int8)

struct m.source

struct m.rights {
	rank: uint16 -- lower = more powerful except 0 = regular user
	-- creating staff automatically assigns rank immediately below you
	quota: uint32 -- # of allowed tweets per day; 0 = no limit
	
	-- user powers -- default on
	login: bool
	visible: bool
	post: bool
	shout: bool
	propagate: bool
	upload: bool

	-- admin powers -- default off
	ban: bool
	config: bool
	censor: bool
	suspend: bool
	rebrand: bool -- modify site's brand identity
}

terra m.rights_default()
	return m.rights {
		rank = 0, quota = 1000;
		
		login = true, visible = true, post = true;
		shout = true, propagate = true, upload = true;

		ban = false, config = false, censor = false;
		suspend = false, rebrand = false;
	}
end

struct m.actor {
	id: uint64
	nym: str
	handle: str
	origin: uint64
	bio: str
	rights: m.rights
	key: lib.mem.ptr(uint8)

	xid: str

	source: &m.source
}

struct m.range {
	time: bool
	union {
		from_time: m.timepoint
		from_idx: uint64
	}
	union {
		to_time: m.timepoint
		to_idx: uint64
	}
}

struct m.post {
	id: uint64
	author: uint64
	subject: str
	body: str
	posted: m.timepoint
	discovered: m.timepoint
	scope: m.scope.t
	mentions: lib.mem.ptr(uint64)
	circles: lib.mem.ptr(uint64) --only meaningful if scope is set to circle
	convo: uint64
	parent: uint64

	source: &m.source
}

local cnf = terralib.memoize(function(ty,rty)
	rty = rty or ty
	return struct {
		enum: {&opaque, uint64, rawstring} -> intptr
		get: {&opaque, uint64, rawstring} -> rty
		set: {&opaque, uint64, rawstring, ty} -> {}
		reset: {&opaque, uint64, rawstring} -> {}
	}
end)

struct m.notif {
	kind: m.notiftype.t
	when: uint64
	union {
		post: uint64
		reaction: int8[8]
	}
}

struct m.inet {
	pv: uint8 -- 0 = null, 4 = ipv4, 6 = ipv6
	union {
		v4: uint8[4]
		v6: uint8[16]
	}
	union {
		fixbits: uint8 -- for cidr
		port: uint16 -- for origin
	}
}

terra m.inet:cidr_str()
	if self.pv == 4 then
		var maxsz = 3*4 + 3 + 1
	elseif self.pv == 6 then
		var bits = 128
		var bytes = bits / 8
		var hexchs = bytes * 2
		var segs = hexchs / 4
		var seps = segs - 1
		var maxsz = hexchs + seps + 1
	else return nil end
end

struct m.auth {
	aid: uint64
	uid: uint64
	aname: str
	netmask: m.inet
	restrict: lib.mem.ptr(rawstring)
	blacklist: bool
}


-- backends only handle content on the local server
struct m.backend { id: rawstring
	open: &m.source -> &opaque
	close: &m.source -> {}

	conf_get: {&m.source, rawstring} -> lib.mem.ptr(int8)
	conf_set: {&m.source, rawstring, rawstring} -> {}
	conf_reset: {&m.source, rawstring} -> {}

	actor_save: {&m.source, m.actor} -> bool
	actor_create: {&m.source, m.actor} -> bool
	actor_fetch_xid: {&m.source, rawstring} -> lib.mem.ptr(m.actor)
	actor_fetch_uid: {&m.source, uint64} -> lib.mem.ptr(m.actor)
	actor_notif_fetch_uid: {&m.source, uint64} -> lib.mem.ptr(m.notif)
	actor_enum: {&m.source} -> lib.mem.ptr(&m.actor)
	actor_enum_local: {&m.source} -> lib.mem.ptr(&m.actor)

	actor_auth_how: {&m.source, m.inet, rawstring} -> m.credset
		-- returns a set of auth method categories that are available for a
		-- given user from a certain origin
			-- origin: inet
			-- handle: rawstring
	actor_auth_otp: {&m.source, m.inet, rawstring, rawstring} -> uint64
	actor_auth_pw: {&m.source, m.inet, rawstring, rawstring} -> uint64
		-- handles password-based logins against hashed passwords
			-- origin: inet
			-- handle: rawstring
			-- token:  rawstring
	actor_auth_tls:    {&m.source, m.inet, rawstring} -> uint64
		-- handles implicit authentication performed as part of an TLS connection
			-- origin: inet
			-- fingerprint: rawstring
	actor_auth_api:    {&m.source, m.inet, rawstring, rawstring} -> uint64
		-- handles API authentication
			-- origin: inet
			-- handle: rawstring
			-- key:    rawstring (X-API-Key)
	actor_auth_record_fetch: {&m.source, uint64} -> lib.mem.ptr(m.auth)

	actor_conf_str: cnf(rawstring, lib.mem.ptr(int8))
	actor_conf_int: cnf(intptr, lib.stat(intptr))

	post_save: {&m.source, &m.post} -> bool
	post_create: {&m.source, &m.post} -> bool
	actor_post_fetch_uid: {&m.source, uint64, m.range} -> lib.mem.ptr(m.post)
	convo_fetch_xid: {&m.source,rawstring} -> lib.mem.ptr(m.post)
	convo_fetch_uid: {&m.source,uint64} -> lib.mem.ptr(m.post)

	actor_timeline_fetch_uid: {&m.source, uint64, m.range} -> lib.mem.ptr(m.post)
	instance_timeline_fetch: {&m.source, m.range} -> lib.mem.ptr(m.post)
}

struct m.source {
	backend: &m.backend
	id: lib.mem.ptr(int8)
	handle: &opaque
	string: lib.mem.ptr(int8)
}
terra m.source:free()
	self.id:free()
	self.string:free()
end
m.source.metamethods.__methodmissing = macro(function(meth, obj, ...)
	local q = {...}
	-- syntax sugar to forward unrecognized calls onto the backend
	return `obj.backend.[meth](&obj, [q])
end)

return m