mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-10-31 16:13:45 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			287 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			287 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //   http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| // author           xeipuuv
 | |
| // author-github    https://github.com/xeipuuv
 | |
| // author-mail      xeipuuv@gmail.com
 | |
| //
 | |
| // repository-name  gojsonschema
 | |
| // repository-desc  An implementation of JSON Schema, based on IETF's draft v4 - Go language.
 | |
| //
 | |
| // description		Different strategies to load JSON files.
 | |
| // 					Includes References (file and HTTP), JSON strings and Go types.
 | |
| //
 | |
| // created          01-02-2015
 | |
| 
 | |
| package gojsonschema
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"encoding/json"
 | |
| 	"errors"
 | |
| 	"io"
 | |
| 	"io/ioutil"
 | |
| 	"net/http"
 | |
| 	"path/filepath"
 | |
| 	"runtime"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/xeipuuv/gojsonreference"
 | |
| )
 | |
| 
 | |
| // JSON loader interface
 | |
| 
 | |
| type JSONLoader interface {
 | |
| 	jsonSource() interface{}
 | |
| 	loadJSON() (interface{}, error)
 | |
| 	loadSchema() (*Schema, error)
 | |
| }
 | |
| 
 | |
| // JSON Reference loader
 | |
| // references are used to load JSONs from files and HTTP
 | |
| 
 | |
| type jsonReferenceLoader struct {
 | |
| 	source string
 | |
| }
 | |
| 
 | |
| func (l *jsonReferenceLoader) jsonSource() interface{} {
 | |
| 	return l.source
 | |
| }
 | |
| 
 | |
| func NewReferenceLoader(source string) *jsonReferenceLoader {
 | |
| 	return &jsonReferenceLoader{source: source}
 | |
| }
 | |
| 
 | |
| func (l *jsonReferenceLoader) loadJSON() (interface{}, error) {
 | |
| 
 | |
| 	var err error
 | |
| 
 | |
| 	reference, err := gojsonreference.NewJsonReference(l.jsonSource().(string))
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	refToUrl := reference
 | |
| 	refToUrl.GetUrl().Fragment = ""
 | |
| 
 | |
| 	var document interface{}
 | |
| 
 | |
| 	if reference.HasFileScheme {
 | |
| 
 | |
| 		filename := strings.Replace(refToUrl.String(), "file://", "", -1)
 | |
| 		if runtime.GOOS == "windows" {
 | |
| 			// on Windows, a file URL may have an extra leading slash, use slashes
 | |
| 			// instead of backslashes, and have spaces escaped
 | |
| 			if strings.HasPrefix(filename, "/") {
 | |
| 				filename = filename[1:]
 | |
| 			}
 | |
| 			filename = filepath.FromSlash(filename)
 | |
| 			filename = strings.Replace(filename, "%20", " ", -1)
 | |
| 		}
 | |
| 
 | |
| 		document, err = l.loadFromFile(filename)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 	} else {
 | |
| 
 | |
| 		document, err = l.loadFromHTTP(refToUrl.String())
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	return document, nil
 | |
| 
 | |
| }
 | |
| 
 | |
| func (l *jsonReferenceLoader) loadSchema() (*Schema, error) {
 | |
| 
 | |
| 	var err error
 | |
| 
 | |
| 	d := Schema{}
 | |
| 	d.pool = newSchemaPool()
 | |
| 	d.referencePool = newSchemaReferencePool()
 | |
| 
 | |
| 	d.documentReference, err = gojsonreference.NewJsonReference(l.jsonSource().(string))
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	spd, err := d.pool.GetDocument(d.documentReference)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	err = d.parse(spd.Document)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return &d, nil
 | |
| 
 | |
| }
 | |
| 
 | |
| func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error) {
 | |
| 
 | |
| 	resp, err := http.Get(address)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	// must return HTTP Status 200 OK
 | |
| 	if resp.StatusCode != http.StatusOK {
 | |
| 		return nil, errors.New(formatErrorDescription(Locale.httpBadStatus(), ErrorDetails{"status": resp.Status}))
 | |
| 	}
 | |
| 
 | |
| 	bodyBuff, err := ioutil.ReadAll(resp.Body)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return decodeJsonUsingNumber(bytes.NewReader(bodyBuff))
 | |
| 
 | |
| }
 | |
| 
 | |
| func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) {
 | |
| 
 | |
| 	bodyBuff, err := ioutil.ReadFile(path)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return decodeJsonUsingNumber(bytes.NewReader(bodyBuff))
 | |
| 
 | |
| }
 | |
| 
 | |
| // JSON string loader
 | |
| 
 | |
| type jsonStringLoader struct {
 | |
| 	source string
 | |
| }
 | |
| 
 | |
| func (l *jsonStringLoader) jsonSource() interface{} {
 | |
| 	return l.source
 | |
| }
 | |
| 
 | |
| func NewStringLoader(source string) *jsonStringLoader {
 | |
| 	return &jsonStringLoader{source: source}
 | |
| }
 | |
| 
 | |
| func (l *jsonStringLoader) loadJSON() (interface{}, error) {
 | |
| 
 | |
| 	return decodeJsonUsingNumber(strings.NewReader(l.jsonSource().(string)))
 | |
| 
 | |
| }
 | |
| 
 | |
| func (l *jsonStringLoader) loadSchema() (*Schema, error) {
 | |
| 
 | |
| 	var err error
 | |
| 
 | |
| 	document, err := l.loadJSON()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	d := Schema{}
 | |
| 	d.pool = newSchemaPool()
 | |
| 	d.referencePool = newSchemaReferencePool()
 | |
| 	d.documentReference, err = gojsonreference.NewJsonReference("#")
 | |
| 	d.pool.SetStandaloneDocument(document)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	err = d.parse(document)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return &d, nil
 | |
| 
 | |
| }
 | |
| 
 | |
| // JSON Go (types) loader
 | |
| // used to load JSONs from the code as maps, interface{}, structs ...
 | |
| 
 | |
| type jsonGoLoader struct {
 | |
| 	source interface{}
 | |
| }
 | |
| 
 | |
| func (l *jsonGoLoader) jsonSource() interface{} {
 | |
| 	return l.source
 | |
| }
 | |
| 
 | |
| func NewGoLoader(source interface{}) *jsonGoLoader {
 | |
| 	return &jsonGoLoader{source: source}
 | |
| }
 | |
| 
 | |
| func (l *jsonGoLoader) loadJSON() (interface{}, error) {
 | |
| 
 | |
| 	// convert it to a compliant JSON first to avoid types "mismatches"
 | |
| 
 | |
| 	jsonBytes, err := json.Marshal(l.jsonSource())
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return decodeJsonUsingNumber(bytes.NewReader(jsonBytes))
 | |
| 
 | |
| }
 | |
| 
 | |
| func (l *jsonGoLoader) loadSchema() (*Schema, error) {
 | |
| 
 | |
| 	var err error
 | |
| 
 | |
| 	document, err := l.loadJSON()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	d := Schema{}
 | |
| 	d.pool = newSchemaPool()
 | |
| 	d.referencePool = newSchemaReferencePool()
 | |
| 	d.documentReference, err = gojsonreference.NewJsonReference("#")
 | |
| 	d.pool.SetStandaloneDocument(document)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	err = d.parse(document)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return &d, nil
 | |
| 
 | |
| }
 | |
| 
 | |
| func decodeJsonUsingNumber(r io.Reader) (interface{}, error) {
 | |
| 
 | |
| 	var document interface{}
 | |
| 
 | |
| 	decoder := json.NewDecoder(r)
 | |
| 	decoder.UseNumber()
 | |
| 
 | |
| 	err := decoder.Decode(&document)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return document, nil
 | |
| 
 | |
| }
 | 
