mirror of
https://github.com/derfenix/webarchive.git
synced 2026-03-11 21:35:34 +03:00
web ui: index and basic details page, api refactoring
This commit is contained in:
@@ -534,14 +534,20 @@ func (s *Page) encodeFields(e *jx.Encoder) {
|
||||
e.FieldStart("status")
|
||||
s.Status.Encode(e)
|
||||
}
|
||||
{
|
||||
|
||||
e.FieldStart("meta")
|
||||
s.Meta.Encode(e)
|
||||
}
|
||||
}
|
||||
|
||||
var jsonFieldsNameOfPage = [5]string{
|
||||
var jsonFieldsNameOfPage = [6]string{
|
||||
0: "id",
|
||||
1: "url",
|
||||
2: "created",
|
||||
3: "formats",
|
||||
4: "status",
|
||||
5: "meta",
|
||||
}
|
||||
|
||||
// Decode decodes Page from json.
|
||||
@@ -617,6 +623,16 @@ func (s *Page) Decode(d *jx.Decoder) error {
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"status\"")
|
||||
}
|
||||
case "meta":
|
||||
requiredBitSet[0] |= 1 << 5
|
||||
if err := func() error {
|
||||
if err := s.Meta.Decode(d); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"meta\"")
|
||||
}
|
||||
default:
|
||||
return d.Skip()
|
||||
}
|
||||
@@ -627,7 +643,7 @@ func (s *Page) Decode(d *jx.Decoder) error {
|
||||
// Validate required fields.
|
||||
var failures []validate.FieldError
|
||||
for i, mask := range [1]uint8{
|
||||
0b00011111,
|
||||
0b00111111,
|
||||
} {
|
||||
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
|
||||
// Mask only required fields and check equality to mask using XOR.
|
||||
@@ -673,6 +689,138 @@ func (s *Page) UnmarshalJSON(data []byte) error {
|
||||
return s.Decode(d)
|
||||
}
|
||||
|
||||
// Encode implements json.Marshaler.
|
||||
func (s *PageMeta) Encode(e *jx.Encoder) {
|
||||
e.ObjStart()
|
||||
s.encodeFields(e)
|
||||
e.ObjEnd()
|
||||
}
|
||||
|
||||
// encodeFields encodes fields.
|
||||
func (s *PageMeta) encodeFields(e *jx.Encoder) {
|
||||
{
|
||||
|
||||
e.FieldStart("title")
|
||||
e.Str(s.Title)
|
||||
}
|
||||
{
|
||||
|
||||
e.FieldStart("description")
|
||||
e.Str(s.Description)
|
||||
}
|
||||
{
|
||||
if s.Error.Set {
|
||||
e.FieldStart("error")
|
||||
s.Error.Encode(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var jsonFieldsNameOfPageMeta = [3]string{
|
||||
0: "title",
|
||||
1: "description",
|
||||
2: "error",
|
||||
}
|
||||
|
||||
// Decode decodes PageMeta from json.
|
||||
func (s *PageMeta) Decode(d *jx.Decoder) error {
|
||||
if s == nil {
|
||||
return errors.New("invalid: unable to decode PageMeta to nil")
|
||||
}
|
||||
var requiredBitSet [1]uint8
|
||||
|
||||
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
|
||||
switch string(k) {
|
||||
case "title":
|
||||
requiredBitSet[0] |= 1 << 0
|
||||
if err := func() error {
|
||||
v, err := d.Str()
|
||||
s.Title = string(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"title\"")
|
||||
}
|
||||
case "description":
|
||||
requiredBitSet[0] |= 1 << 1
|
||||
if err := func() error {
|
||||
v, err := d.Str()
|
||||
s.Description = string(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"description\"")
|
||||
}
|
||||
case "error":
|
||||
if err := func() error {
|
||||
s.Error.Reset()
|
||||
if err := s.Error.Decode(d); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"error\"")
|
||||
}
|
||||
default:
|
||||
return d.Skip()
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "decode PageMeta")
|
||||
}
|
||||
// Validate required fields.
|
||||
var failures []validate.FieldError
|
||||
for i, mask := range [1]uint8{
|
||||
0b00000011,
|
||||
} {
|
||||
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
|
||||
// Mask only required fields and check equality to mask using XOR.
|
||||
//
|
||||
// If XOR result is not zero, result is not equal to expected, so some fields are missed.
|
||||
// Bits of fields which would be set are actually bits of missed fields.
|
||||
missed := bits.OnesCount8(result)
|
||||
for bitN := 0; bitN < missed; bitN++ {
|
||||
bitIdx := bits.TrailingZeros8(result)
|
||||
fieldIdx := i*8 + bitIdx
|
||||
var name string
|
||||
if fieldIdx < len(jsonFieldsNameOfPageMeta) {
|
||||
name = jsonFieldsNameOfPageMeta[fieldIdx]
|
||||
} else {
|
||||
name = strconv.Itoa(fieldIdx)
|
||||
}
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: name,
|
||||
Error: validate.ErrFieldRequired,
|
||||
})
|
||||
// Reset bit.
|
||||
result &^= 1 << bitIdx
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements stdjson.Marshaler.
|
||||
func (s *PageMeta) MarshalJSON() ([]byte, error) {
|
||||
e := jx.Encoder{}
|
||||
s.Encode(&e)
|
||||
return e.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements stdjson.Unmarshaler.
|
||||
func (s *PageMeta) UnmarshalJSON(data []byte) error {
|
||||
d := jx.DecodeBytes(data)
|
||||
return s.Decode(d)
|
||||
}
|
||||
|
||||
// Encode implements json.Marshaler.
|
||||
func (s *PageWithResults) Encode(e *jx.Encoder) {
|
||||
e.ObjStart()
|
||||
@@ -711,6 +859,11 @@ func (s *PageWithResults) encodeFields(e *jx.Encoder) {
|
||||
e.FieldStart("status")
|
||||
s.Status.Encode(e)
|
||||
}
|
||||
{
|
||||
|
||||
e.FieldStart("meta")
|
||||
s.Meta.Encode(e)
|
||||
}
|
||||
{
|
||||
|
||||
e.FieldStart("results")
|
||||
@@ -722,13 +875,14 @@ func (s *PageWithResults) encodeFields(e *jx.Encoder) {
|
||||
}
|
||||
}
|
||||
|
||||
var jsonFieldsNameOfPageWithResults = [6]string{
|
||||
var jsonFieldsNameOfPageWithResults = [7]string{
|
||||
0: "id",
|
||||
1: "url",
|
||||
2: "created",
|
||||
3: "formats",
|
||||
4: "status",
|
||||
5: "results",
|
||||
5: "meta",
|
||||
6: "results",
|
||||
}
|
||||
|
||||
// Decode decodes PageWithResults from json.
|
||||
@@ -804,8 +958,18 @@ func (s *PageWithResults) Decode(d *jx.Decoder) error {
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"status\"")
|
||||
}
|
||||
case "results":
|
||||
case "meta":
|
||||
requiredBitSet[0] |= 1 << 5
|
||||
if err := func() error {
|
||||
if err := s.Meta.Decode(d); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"meta\"")
|
||||
}
|
||||
case "results":
|
||||
requiredBitSet[0] |= 1 << 6
|
||||
if err := func() error {
|
||||
s.Results = make([]Result, 0)
|
||||
if err := d.Arr(func(d *jx.Decoder) error {
|
||||
@@ -832,7 +996,7 @@ func (s *PageWithResults) Decode(d *jx.Decoder) error {
|
||||
// Validate required fields.
|
||||
var failures []validate.FieldError
|
||||
for i, mask := range [1]uint8{
|
||||
0b00111111,
|
||||
0b01111111,
|
||||
} {
|
||||
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
|
||||
// Mask only required fields and check equality to mask using XOR.
|
||||
@@ -878,6 +1042,138 @@ func (s *PageWithResults) UnmarshalJSON(data []byte) error {
|
||||
return s.Decode(d)
|
||||
}
|
||||
|
||||
// Encode implements json.Marshaler.
|
||||
func (s *PageWithResultsMeta) Encode(e *jx.Encoder) {
|
||||
e.ObjStart()
|
||||
s.encodeFields(e)
|
||||
e.ObjEnd()
|
||||
}
|
||||
|
||||
// encodeFields encodes fields.
|
||||
func (s *PageWithResultsMeta) encodeFields(e *jx.Encoder) {
|
||||
{
|
||||
|
||||
e.FieldStart("title")
|
||||
e.Str(s.Title)
|
||||
}
|
||||
{
|
||||
|
||||
e.FieldStart("description")
|
||||
e.Str(s.Description)
|
||||
}
|
||||
{
|
||||
if s.Error.Set {
|
||||
e.FieldStart("error")
|
||||
s.Error.Encode(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var jsonFieldsNameOfPageWithResultsMeta = [3]string{
|
||||
0: "title",
|
||||
1: "description",
|
||||
2: "error",
|
||||
}
|
||||
|
||||
// Decode decodes PageWithResultsMeta from json.
|
||||
func (s *PageWithResultsMeta) Decode(d *jx.Decoder) error {
|
||||
if s == nil {
|
||||
return errors.New("invalid: unable to decode PageWithResultsMeta to nil")
|
||||
}
|
||||
var requiredBitSet [1]uint8
|
||||
|
||||
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
|
||||
switch string(k) {
|
||||
case "title":
|
||||
requiredBitSet[0] |= 1 << 0
|
||||
if err := func() error {
|
||||
v, err := d.Str()
|
||||
s.Title = string(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"title\"")
|
||||
}
|
||||
case "description":
|
||||
requiredBitSet[0] |= 1 << 1
|
||||
if err := func() error {
|
||||
v, err := d.Str()
|
||||
s.Description = string(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"description\"")
|
||||
}
|
||||
case "error":
|
||||
if err := func() error {
|
||||
s.Error.Reset()
|
||||
if err := s.Error.Decode(d); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"error\"")
|
||||
}
|
||||
default:
|
||||
return d.Skip()
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "decode PageWithResultsMeta")
|
||||
}
|
||||
// Validate required fields.
|
||||
var failures []validate.FieldError
|
||||
for i, mask := range [1]uint8{
|
||||
0b00000011,
|
||||
} {
|
||||
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
|
||||
// Mask only required fields and check equality to mask using XOR.
|
||||
//
|
||||
// If XOR result is not zero, result is not equal to expected, so some fields are missed.
|
||||
// Bits of fields which would be set are actually bits of missed fields.
|
||||
missed := bits.OnesCount8(result)
|
||||
for bitN := 0; bitN < missed; bitN++ {
|
||||
bitIdx := bits.TrailingZeros8(result)
|
||||
fieldIdx := i*8 + bitIdx
|
||||
var name string
|
||||
if fieldIdx < len(jsonFieldsNameOfPageWithResultsMeta) {
|
||||
name = jsonFieldsNameOfPageWithResultsMeta[fieldIdx]
|
||||
} else {
|
||||
name = strconv.Itoa(fieldIdx)
|
||||
}
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: name,
|
||||
Error: validate.ErrFieldRequired,
|
||||
})
|
||||
// Reset bit.
|
||||
result &^= 1 << bitIdx
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements stdjson.Marshaler.
|
||||
func (s *PageWithResultsMeta) MarshalJSON() ([]byte, error) {
|
||||
e := jx.Encoder{}
|
||||
s.Encode(&e)
|
||||
return e.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements stdjson.Unmarshaler.
|
||||
func (s *PageWithResultsMeta) UnmarshalJSON(data []byte) error {
|
||||
d := jx.DecodeBytes(data)
|
||||
return s.Decode(d)
|
||||
}
|
||||
|
||||
// Encode encodes Pages as json.
|
||||
func (s Pages) Encode(e *jx.Encoder) {
|
||||
unwrapped := []Page(s)
|
||||
|
||||
Reference in New Issue
Block a user