types (#1)
All checks were successful
continuous-integration/drone/push Build is passing

Co-authored-by: andrey1s <andrey@4devs.pro>
Reviewed-on: #1
Co-authored-by: andrey <andrey@4devs.io>
Co-committed-by: andrey <andrey@4devs.io>
This commit was merged in pull request #1.
This commit is contained in:
2022-09-30 10:14:29 +03:00
parent 779846fe9a
commit 8ff25d212d
16 changed files with 25869 additions and 10249 deletions

42
.drone.yml Normal file
View File

@@ -0,0 +1,42 @@
kind: pipeline
name: default
steps:
- name: golangci-lint
image: golangci/golangci-lint:v1.49
volumes:
- name: deps
path: /go/src/mod
commands:
- golangci-lint run --timeout 5m
- name: test
image: golang
volumes:
- name: deps
path: /go/src/mod
commands:
- go test ./...
- name: scripts golangci-lint
image: golangci/golangci-lint:v1.49
volumes:
- name: deps
path: /go/src/mod
commands:
- cd scripts
- golangci-lint run --timeout 5m
- name: scripts test
image: golang
volumes:
- name: deps
path: /go/src/mod
commands:
- cd scripts
- go test ./...
volumes:
- name: deps
temp: {}

43
.golangci.yml Normal file
View File

@@ -0,0 +1,43 @@
linters-settings:
dupl:
threshold: 100
funlen:
lines: 100
statements: 50
goconst:
min-len: 2
min-occurrences: 2
gocyclo:
min-complexity: 15
golint:
min-confidence: 0
govet:
check-shadowing: true
lll:
line-length: 140
maligned:
suggest-new: true
misspell:
locale: US
varnamelen:
min-name-length: 2
linters:
enable-all: true
disable:
- varcheck
- maligned
- scopelint
- nosnakecase
- ifshort
- golint
- interfacer
- structcheck
- deadcode
- exhaustivestruct
- exhaustruct
# is disabled because of generics. You can track the evolution of the generics support by following the https://github.com/golangci/golangci-lint/issues/2649
- rowserrcheck
- sqlclosecheck
- wastedassign

View File

@@ -1,2 +1,3 @@
# mime
[![Build Status](https://drone.gitoa.ru/api/badges/go-4devs/mime/status.svg)](https://drone.gitoa.ru/go-4devs/mime)

17292
extension.go

File diff suppressed because it is too large Load Diff

13352
mime.go

File diff suppressed because it is too large Load Diff

1666
mime.json

File diff suppressed because it is too large Load Diff

3394
mime.yaml Normal file

File diff suppressed because it is too large Load Diff

36
mime_example_test.go Normal file
View File

@@ -0,0 +1,36 @@
package mime_test
import (
"fmt"
"gitoa.ru/go-4devs/mime"
)
func ExampleMime_String() {
fmt.Printf("%v", mime.TextHTML)
// Output:
// text/html
}
func ExampleMime_Is() {
fmt.Printf("%v\n%v",
mime.TextHTML.Is(mime.ApplicationJSON, mime.ApplicationJavascript),
mime.TextHTML.Is(mime.ApplicationJavascript, mime.TextHTML),
)
// Output:
// false
// true
}
func ExampleMime_ExtTypes() {
fmt.Printf("%v\n%v",
mime.TextHTML.ExtTypes(),
mime.ApplicationJavascript.ExtTypes(),
)
// Output:
// [html htm shtml]
// [js mjs jsm]
}

View File

@@ -27,7 +27,7 @@ func Mime() *console.Command {
Name: "mime",
Description: "generate mime from file",
Configure: func(ctx context.Context, cfg *input.Definition) error {
cfg.SetArgument(ArgFile, "file", argument.Required)
cfg.SetArgument(ArgFile, "yaml file", argument.Required)
cfg.SetOptions(
option.String(OptExtTpl, "extension template", option.Default("mime/tpl/extension.text.tmpl")),
option.String(OptExtPackage, "extension package", option.Default("mime")),

View File

@@ -6,4 +6,5 @@ require (
github.com/achiku/varfmt v0.0.0-20160708124000-f820e1efecee
gitoa.ru/go-4devs/closer v0.1.1
gitoa.ru/go-4devs/console v0.1.2
gopkg.in/yaml.v3 v3.0.1
)

View File

@@ -3,8 +3,10 @@ github.com/achiku/varfmt v0.0.0-20160708124000-f820e1efecee/go.mod h1:RKS7P4TSY/
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -18,6 +20,7 @@ gitoa.ru/go-4devs/closer v0.1.1/go.mod h1:S+QAdgSt4CVLH3v3YZK1Mukl7SVn2Z0CYj0oJQ
gitoa.ru/go-4devs/console v0.1.2 h1:SsQWLSClXFwWFseH6CGKQfmCtG84aHOiaFHG3oZlJ8s=
gitoa.ru/go-4devs/console v0.1.2/go.mod h1:ddqmjQ0yr9v+oa5E3Bu3X/SUcws/ENR5f5cz1g5fHbk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@@ -11,8 +11,10 @@ import (
func main() {
ctx, cancel := context.WithCancel(context.Background())
closer.AddLast(func() error {
cancel()
return nil
})

View File

@@ -1,31 +1,105 @@
package mime
import (
"encoding/json"
"errors"
"fmt"
"go/format"
"io/ioutil"
"os"
"path"
"text/template"
"gopkg.in/yaml.v3"
)
var (
ErrDuplicate = errors.New("duplicate")
ErrNotFound = errors.New("not found")
)
const (
NameExt = "ext"
NameMime = "mime"
)
type Config struct {
Source string
Mimes map[string][]string
Mimes []Data `yaml:"mime"`
MimePrefix string
MimeTpl string
MimeResult string
MimePackage string
Extensions map[string][]string
Extensions []Data `yaml:"ext"`
ExtPrefix string
ExtTpl string
ExtResult string
ExtPackage string
}
type Data struct {
Name string `yaml:"name"`
ID int `yaml:"id"`
Value []string `yaml:"value,omitempty"`
}
func (c *Config) Base(name string) string {
switch name {
case NameExt:
return path.Base(c.ExtTpl)
case NameMime:
return path.Base(c.MimeTpl)
}
return ""
}
func (c *Config) Result(name string) string {
switch name {
case NameExt:
return c.ExtResult
case NameMime:
return c.MimeResult
}
return ""
}
func (c *Config) ValidateAndFillExt() error {
mimes := make(map[string]int)
mimeIDs := make(map[int]string)
extIndex := make(map[string]int)
for idx, ext := range c.Extensions {
if _, ok := extIndex[ext.Name]; ok {
return fmt.Errorf("extension %v %w: with id %v", ext.Name, ErrDuplicate, c.Extensions[extIndex[ext.Name]].ID)
}
extIndex[ext.Name] = idx
}
for _, mime := range c.Mimes {
if _, ok := mimes[mime.Name]; ok {
return fmt.Errorf("mime %v %w: with id %v", mime.Name, ErrDuplicate, mimes[mime.Name])
}
if _, ok := mimeIDs[mime.ID]; ok {
return fmt.Errorf("ID %v %w: with name %v", mime.ID, ErrDuplicate, mimeIDs[mime.ID])
}
for _, ext := range mime.Value {
idx, ok := extIndex[ext]
if !ok {
return fmt.Errorf("%w ext by %v", ErrNotFound, mime.Name)
}
c.Extensions[idx].Value = append(c.Extensions[idx].Value, mime.Name)
}
}
return nil
}
func WithExtTpl(name string) Option {
return func(c *Config) {
c.ExtTpl = name
@@ -78,11 +152,9 @@ func Generate(fileName string, opts ...Option) error {
ExtPrefix: "Ext",
ExtTpl: "mime/tpl/extension.text.tmpl",
ExtResult: "extension.go",
Extensions: make(map[string][]string),
ExtPackage: "mime",
MimeTpl: "mime/tpl/mime.text.tmpl",
Mimes: make(map[string][]string),
MimePrefix: "",
MimeResult: "mime.go",
MimePackage: "mime",
@@ -92,46 +164,47 @@ func Generate(fileName string, opts ...Option) error {
opt(&cfg)
}
data, err := os.ReadFile(fileName)
if err != nil {
return fmt.Errorf("read file:%w", err)
data, cerr := os.ReadFile(fileName)
if cerr != nil {
return fmt.Errorf("read file:%w", cerr)
}
if err := json.Unmarshal(data, &cfg.Mimes); err != nil {
return fmt.Errorf("unmarshal:%w", err)
if uerr := yaml.Unmarshal(data, &cfg); uerr != nil {
return fmt.Errorf("unmarshal:%w", uerr)
}
cfg.Extensions = extensions(cfg.Mimes)
if validErr := cfg.ValidateAndFillExt(); validErr != nil {
return fmt.Errorf("config:%w", validErr)
}
template, err := template.New("mimes").Funcs(funcMap()).ParseFiles(cfg.ExtTpl, cfg.MimeTpl)
if err != nil {
return fmt.Errorf("ext template:%w", err)
}
extFile, err := os.Create(cfg.ExtResult)
if exErr := Create(template, NameExt, cfg); exErr != nil {
return fmt.Errorf("ext create:%w", exErr)
}
if mimeErr := Create(template, NameMime, cfg); mimeErr != nil {
return fmt.Errorf("mime create:%w", mimeErr)
}
return nil
}
func Create(tpl *template.Template, name string, cfg Config) error {
extFile, err := os.Create(cfg.Result(name))
if err != nil {
return fmt.Errorf("ext file:%w", err)
}
if err := template.ExecuteTemplate(extFile, path.Base(cfg.ExtTpl), cfg); err != nil {
return fmt.Errorf("ext execute:%w", err)
if exErr := tpl.ExecuteTemplate(extFile, cfg.Base(name), cfg); exErr != nil {
return fmt.Errorf("ext execute:%w", exErr)
}
if err := Format(extFile.Name()); err != nil {
return fmt.Errorf("format ext:%w", err)
}
mimeFile, err := os.Create(cfg.MimeResult)
if err != nil {
return fmt.Errorf("mime file:%w", err)
}
if err := template.ExecuteTemplate(mimeFile, path.Base(cfg.MimeTpl), cfg); err != nil {
return fmt.Errorf("mime execute:%w", err)
}
if err := Format(mimeFile.Name()); err != nil {
return fmt.Errorf("format mime:%w", err)
if formatErr := Format(extFile.Name()); formatErr != nil {
return fmt.Errorf("format ext:%w", formatErr)
}
return nil
@@ -139,13 +212,14 @@ func Generate(fileName string, opts ...Option) error {
// Format file and write it.
func Format(name string) error {
in, err := ioutil.ReadFile(name)
in, err := os.ReadFile(name)
if err != nil {
return err
return fmt.Errorf("read file:%w", err)
}
out, err := format.Source(in)
if err != nil {
return err
return fmt.Errorf("format source:%w", err)
}
file, err := os.Create(name)
@@ -159,19 +233,3 @@ func Format(name string) error {
return nil
}
func extensions(mimes map[string][]string) map[string][]string {
out := make(map[string][]string)
for mime, exts := range mimes {
for _, ext := range exts {
if _, ok := out[ext]; ok {
out[ext] = append(out[ext], mime)
continue
}
out[ext] = []string{ext}
}
}
return out
}

View File

@@ -1,19 +1,58 @@
// Code generated by gitoa.ru/go-4devs/mime and sourse {{.Source}}
package {{.ExtPackage}}
const (
{{- range $key, $value := .Extensions }}
{{ name $.ExtPrefix $key }} = "{{ $key }}"
{{- end}}
)
import "fmt"
func Mime(name string) []string {
switch name {
{{- range $key, $value := .Extensions }}
case {{ name $.ExtPrefix $key }}:
return {{ value $value }}
type Ext int
type ExtTypes []Ext
func (v Ext) Is(types ...Ext) bool {
for _, ext := range types {
if ext == v {
return true
}
}
return false
}
func (v Ext) String() string {
switch v {
{{- range $value := .Extensions }}
case {{ name $.ExtPrefix $value.Name }}:
return "{{- $value.Name -}}"
{{- end}}
}
return fmt.Sprintf("Ext(%d)",v)
}
func (v Ext) MimeTypes() MimeTypes{
switch v {
{{- range $value := .Extensions }}
case {{ name $.ExtPrefix $value.Name }}:
return MimeTypes{ {{- value $.MimePrefix $value.Value -}} }
{{- end}}
}
return nil
}
const (
{{- range $value := .Extensions }}
{{ name $.ExtPrefix $value.Name }} Ext = {{ $value.ID }}
{{- end}}
)
func ExtFromString(name string) Ext {
switch name {
{{- range $value := .Extensions }}
case "{{- $value.Name -}}":
return {{ name $.ExtPrefix $value.Name }}
{{- end}}
}
return 0
}

View File

@@ -1,19 +1,57 @@
// Code generated by gitoa.ru/go-4devs/mime and sourse {{.Source}}
package {{.MimePackage}}
const (
{{- range $key, $value := .Mimes }}
{{ name $.MimePrefix $key }} = "{{ $key }}"
{{- end}}
)
import "fmt"
func Extension(name string) []string {
switch name {
{{- range $key, $value := .Mimes }}
case {{ name $.MimePrefix $key }}:
return {{ value $value }}
type Mime int
type MimeTypes []Mime
func (v Mime) Is(types ...Mime) bool {
for _, mime := range types {
if mime == v {
return true
}
}
return false
}
func (v Mime) String() string {
switch v {
{{- range $value := .Mimes }}
case {{ name $.MimePrefix $value.Name }}:
return "{{- $value.Name -}}"
{{- end}}
}
return fmt.Sprintf("Mime(%d)",v)
}
func (v Mime) ExtTypes() ExtTypes{
switch v {
{{- range $value := .Mimes }}
case {{ name $.MimePrefix $value.Name }}:
return []Ext{ {{- value $.ExtPrefix $value.Value -}} }
{{- end}}
}
return nil
}
const (
{{- range $value := .Mimes }}
{{ name $.MimePrefix $value.Name }} Mime = {{ $value.ID }}
{{- end}}
)
func MimeFromString(name string) Mime {
switch name {
{{- range $value := .Mimes }}
case "{{- $value.Name -}}":
return {{ name $.MimePrefix $value.Name }}
{{- end}}
}
return 0
}

View File

@@ -1,7 +1,7 @@
package mime
import (
"fmt"
"bytes"
"strings"
"unicode"
@@ -27,6 +27,11 @@ func VarName(prefix, name string) string {
return varfmt.PublicVarName(prefix + "_" + name)
}
func Value(val []string) string {
return fmt.Sprintf("%#v", val)
func Value(prefix string, val []string) string {
var out bytes.Buffer
for _, name := range val {
out.WriteString(VarName(prefix, name) + ",")
}
return out.String()
}