File: file_format.go

package info (click to toggle)
golang-code.forgejo-f3-gof3 3.11.0-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 1,952 kB
  • sloc: sh: 100; makefile: 65
file content (109 lines) | stat: -rw-r--r-- 2,437 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT

package f3

import (
	"encoding/json"
	"fmt"
	"os"

	"github.com/santhosh-tekuri/jsonschema/v6"
)

// Load project data from file, with optional validation
func Load(filename string, data any, validation bool) error {
	bs, err := os.ReadFile(filename)
	if err != nil {
		return err
	}

	if validation {
		err := validate(bs, data)
		if err != nil {
			return err
		}
	}
	return unmarshal(bs, data)
}

func Store(filename string, data any) error {
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()
	bs, err := json.MarshalIndent(data, "", "    ")
	if err != nil {
		return err
	}
	if _, err := f.Write(bs); err != nil {
		return err
	}
	if _, err := f.Write([]byte("\n")); err != nil {
		return err
	}
	return nil
}

func unmarshal(bs []byte, data any) error {
	return json.Unmarshal(bs, data)
}

func getSchema(filename string) (*jsonschema.Schema, error) {
	c := jsonschema.NewCompiler()
	return c.Compile(filename)
}

func validate(bs []byte, datatype any) error {
	var v any
	err := unmarshal(bs, &v)
	if err != nil {
		return err
	}

	var schemaFilename string
	switch datatype := datatype.(type) {
	case *User:
		schemaFilename = "schemas/user.json"
	case *Organization:
		schemaFilename = "schemas/organization.json"
	case *Project:
		schemaFilename = "schemas/project.json"
	case *Topic:
		schemaFilename = "schemas/topic.json"
	case *Issue:
		schemaFilename = "schemas/issue.json"
	case *PullRequest:
		schemaFilename = "schemas/pullrequest.json"
	case *Label:
		schemaFilename = "schemas/label.json"
	case *Milestone:
		schemaFilename = "schemas/milestone.json"
	case *Release:
		schemaFilename = "schemas/release.json"
	case *Attachment:
		schemaFilename = "schemas/attachment.json"
	case *Comment:
		schemaFilename = "schemas/comment.json"
	case *Reaction:
		schemaFilename = "schemas/reaction.json"
	case *Repository:
		schemaFilename = "schemas/repository.json"
	case *Review:
		schemaFilename = "schemas/review.json"
	case *ReviewComment:
		schemaFilename = "schemas/reviewcomment.json"
	case *CI:
		schemaFilename = "schemas/ci.json"
	default:
		return fmt.Errorf("file_format:validate: %T does not have a schema that could be used for validation", datatype)
	}

	sch, err := getSchema(schemaFilename)
	if err != nil {
		return err
	}
	return sch.Validate(v)
}