github.com/alimy/mir/v4@v4.1.0/internal/naming/snake_ns.go (about)

     1  // Copyright 2020 Michael Li <alimy@gility.net>. All rights reserved.
     2  // Use of this source code is governed by Apache License 2.0 that
     3  // can be found in the LICENSE file.
     4  
     5  package naming
     6  
     7  import (
     8  	"bytes"
     9  	"strings"
    10  )
    11  
    12  // snakeNamingStrategy snake naming strategy implement
    13  // This implement is inspiration from https://github.com/jingzhu/gorm's naming logic.
    14  type snakeNamingStrategy struct {
    15  	initialismsReplacer *strings.Replacer
    16  }
    17  
    18  func (s *snakeNamingStrategy) Naming(name string) string {
    19  	if name == "" {
    20  		return ""
    21  	}
    22  
    23  	var lastCase, currCase, nextCase, nextNumber bool
    24  	value := s.initialismsReplacer.Replace(name)
    25  	buf := bytes.NewBufferString("")
    26  	lower, upper := false, true
    27  	for i, v := range value[:len(value)-1] {
    28  		nextCase = value[i+1] >= 'A' && value[i+1] <= 'Z'
    29  		nextNumber = value[i+1] >= '0' && value[i+1] <= '9'
    30  		if i > 0 {
    31  			if currCase == upper {
    32  				if lastCase == upper && (nextCase == upper || nextNumber == upper) {
    33  					buf.WriteRune(v)
    34  				} else {
    35  					if value[i-1] != '_' && value[i+1] != '_' {
    36  						buf.WriteRune('_')
    37  					}
    38  					buf.WriteRune(v)
    39  				}
    40  			} else {
    41  				buf.WriteRune(v)
    42  				if i == len(value)-2 && (nextCase == upper && nextNumber == lower) {
    43  					buf.WriteRune('_')
    44  				}
    45  			}
    46  		} else {
    47  			currCase = upper
    48  			buf.WriteRune(v)
    49  		}
    50  		lastCase, currCase = currCase, nextCase
    51  	}
    52  
    53  	buf.WriteByte(value[len(value)-1])
    54  	res := strings.ToLower(buf.String())
    55  	return res
    56  }
    57  
    58  // NewSnakeNamingStrategy return snake naming strategy instance
    59  func NewSnakeNamingStrategy() NamingStrategy {
    60  	// Copied from golint
    61  	initialisms := []string{
    62  		"API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP",
    63  		"HTTPS", "ID", "IP", "JSON", "LHS", "QPS", "RAM", "RHS", "RPC", "SLA",
    64  		"SMTP", "SSH", "TLS", "TTL", "UID", "UI", "UUID", "URI", "URL", "UTF8",
    65  		"VM", "XML", "XSRF", "XSS"}
    66  
    67  	var oldnews []string
    68  	for _, initialism := range initialisms {
    69  		oldnews = append(oldnews, initialism, strings.Title(strings.ToLower(initialism)))
    70  	}
    71  	replacer := strings.NewReplacer(oldnews...)
    72  
    73  	return &snakeNamingStrategy{
    74  		initialismsReplacer: replacer,
    75  	}
    76  }