github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/tao/auth/format.go (about) 1 // Copyright (c) 2014, Kevin Walsh. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package auth 16 17 // This file implements Format() functions for pretty-printing elements. 18 // When printed with format verb %v, the "verbose" long form is used. 19 // When printed with format verb %s, the "short" elided form is used. 20 // When printed with other verbs, the output format is unspecified. 21 22 import ( 23 "encoding/base64" 24 "fmt" 25 ) 26 27 // ElisionCutoff is the maximum length a String or Byte can be without being elided. 28 var ElisionCutoff int = 32 29 30 // ElisionLength is the number of characters to show in an elided String or Byte. 31 var ElisionLength int = 24 32 33 // Format outputs a pretty-printed Prin. 34 func (p Prin) Format(out fmt.State, verb rune) { 35 fmt.Fprintf(out, "%s(", p.Type) 36 p.KeyHash.Format(out, verb) 37 fmt.Fprint(out, ")") 38 p.Ext.Format(out, verb) 39 } 40 41 // Format outputs a pretty-printed PrinTail. 42 func (p PrinTail) Format(out fmt.State, verb rune) { 43 fmt.Fprintf(out, "ext") 44 p.Ext.Format(out, verb) 45 } 46 47 // Format outputs a pretty-printed PrinExt. 48 func (e PrinExt) Format(out fmt.State, verb rune) { 49 formatNameAndArg(out, e.Name, e.Arg, verb) 50 } 51 52 // formatNameAndArg outputs a pretty-printed name and argument list using short 53 // or long formats. 54 func formatNameAndArg(out fmt.State, name string, arg []Term, verb rune) { 55 fmt.Fprintf(out, "%s(", name) 56 for i, a := range arg { 57 if i > 0 { 58 fmt.Fprint(out, ", ") 59 } 60 a.Format(out, verb) 61 } 62 fmt.Fprint(out, ")") 63 } 64 65 // Format outputs a pretty-printed SubPrin. 66 func (p SubPrin) Format(out fmt.State, verb rune) { 67 for _, e := range p { 68 fmt.Fprint(out, ".") 69 e.Format(out, verb) 70 } 71 } 72 73 // Format outputs a pretty-printed Str. 74 func (t Str) Format(out fmt.State, verb rune) { 75 if verb == 's' && len(string(t)) > ElisionCutoff { 76 fmt.Fprintf(out, "%q...", string(t)[:ElisionLength]) 77 } else { 78 fmt.Fprintf(out, "%q", string(t)) 79 } 80 } 81 82 // Format outputs a pretty-printed Bytes. 83 func (t Bytes) Format(out fmt.State, verb rune) { 84 if out.Flag('#') { 85 // use alternate format: base64w 86 s := base64.URLEncoding.EncodeToString([]byte(t)) 87 if verb == 's' && len(string(t)) > ElisionCutoff { 88 fmt.Fprintf(out, "{%s...}", s[:ElisionLength]) 89 } else { 90 fmt.Fprintf(out, "{%s}", s) 91 } 92 } else { 93 // use default format: hex 94 if verb == 's' && len(string(t)) > ElisionCutoff { 95 fmt.Fprintf(out, "[%02x...]", []byte(t)[:ElisionLength]) 96 } else { 97 fmt.Fprintf(out, "[%02x]", []byte(t)) 98 } 99 } 100 } 101 102 // Format outputs a pretty-printed Int. 103 func (t Int) Format(out fmt.State, verb rune) { 104 fmt.Fprintf(out, "%d", int64(t)) 105 } 106 107 // Format outputs a pretty-printed TermVar. 108 func (t TermVar) Format(out fmt.State, verb rune) { 109 fmt.Fprint(out, string(t)) 110 } 111 112 // Format outputs a pretty-printed Pred. 113 func (f Pred) Format(out fmt.State, verb rune) { 114 formatNameAndArg(out, f.Name, f.Arg, verb) 115 } 116 117 // Format outputs a pretty-printed Const. 118 func (f Const) Format(out fmt.State, verb rune) { 119 if f == true { 120 fmt.Fprint(out, "true") 121 } else { 122 fmt.Fprint(out, "false") 123 } 124 } 125 126 // Format outputs a pretty-printed Not. 127 func (f Not) Format(out fmt.State, verb rune) { 128 fmt.Fprint(out, "not ") 129 formatFormWithParens(out, precedenceHigh, true, f.Negand, verb) 130 } 131 132 // Format outputs a pretty-printed And. 133 func (f And) Format(out fmt.State, verb rune) { 134 if len(f.Conjunct) == 0 { 135 fmt.Fprint(out, "true") 136 } else if len(f.Conjunct) == 1 { 137 f.Conjunct[0].Format(out, verb) 138 } else { 139 n := len(f.Conjunct) 140 for i, e := range f.Conjunct { 141 if i > 0 { 142 fmt.Fprint(out, " and ") 143 } 144 formatFormWithParens(out, precedenceAnd, i == n-1, e, verb) 145 } 146 } 147 } 148 149 // Format outputs a pretty-printed Or. 150 func (f Or) Format(out fmt.State, verb rune) { 151 if len(f.Disjunct) == 0 { 152 fmt.Fprint(out, "false") 153 } else if len(f.Disjunct) == 1 { 154 f.Disjunct[0].Format(out, verb) 155 } else { 156 n := len(f.Disjunct) 157 for i, e := range f.Disjunct { 158 if i > 0 { 159 fmt.Fprint(out, " or ") 160 } 161 formatFormWithParens(out, precedenceOr, i == n-1, e, verb) 162 } 163 } 164 } 165 166 // Format outputs a pretty-printed Implies. 167 func (f Implies) Format(out fmt.State, verb rune) { 168 formatFormWithParens(out, precedenceLow+1, false, f.Antecedent, verb) 169 fmt.Fprint(out, " implies ") 170 formatFormWithParens(out, precedenceLow, true, f.Consequent, verb) 171 } 172 173 // Format outputs a pretty-printed Speaksfor. 174 func (f Speaksfor) Format(out fmt.State, verb rune) { 175 f.Delegate.Format(out, verb) 176 fmt.Fprint(out, " speaksfor ") 177 f.Delegator.Format(out, verb) 178 } 179 180 // Format outputs a pretty-printed Says. 181 func (f Says) Format(out fmt.State, verb rune) { 182 f.Speaker.Format(out, verb) 183 if f.Commences() { 184 fmt.Fprintf(out, " from %d", *f.Time) 185 } 186 if f.Expires() { 187 fmt.Fprintf(out, " until %d", *f.Expiration) 188 } 189 fmt.Fprint(out, " says ") 190 f.Message.Format(out, verb) 191 } 192 193 // Format outputs a pretty-printed Forall. 194 func (f Forall) Format(out fmt.State, verb rune) { 195 fmt.Fprintf(out, "forall %s: ", f.Var) 196 f.Body.Format(out, verb) 197 } 198 199 // Format outputs a pretty-printed Exists. 200 func (f Exists) Format(out fmt.State, verb rune) { 201 fmt.Fprintf(out, "exists %s: ", f.Var) 202 f.Body.Format(out, verb) 203 } 204 205 const ( 206 precedenceLow = iota // lowest: implies, says, right speaksfor, right forall, right exists 207 precedenceOr 208 precedenceAnd 209 precedenceHigh // not, true, false, Pred, left speaksfor, left forall, left exists 210 ) 211 212 // precedence returns an integer indicating the relative precedence of f. 213 func precedence(f Form, right bool) int { 214 switch f := f.(type) { 215 case Says, Speaksfor, Forall, Exists, *Says, *Speaksfor, *Forall, *Exists: 216 if right { 217 return precedenceHigh 218 } 219 return precedenceLow 220 case Implies, *Implies: 221 return precedenceLow 222 case Or: 223 if len(f.Disjunct) == 0 { 224 return precedenceHigh // Or{} == false 225 } else if len(f.Disjunct) == 1 { 226 return precedence(f.Disjunct[0], right) // Or{f} == f 227 } else { 228 return precedenceOr 229 } 230 case *Or: 231 if len(f.Disjunct) == 0 { 232 return precedenceHigh // Or{} == false 233 } else if len(f.Disjunct) == 1 { 234 return precedence(f.Disjunct[0], right) // Or{f} == f 235 } else { 236 return precedenceOr 237 } 238 case And: 239 if len(f.Conjunct) == 0 { 240 return precedenceHigh // And{} == true 241 } else if len(f.Conjunct) == 1 { 242 return precedence(f.Conjunct[0], right) // And{f} == f 243 } else { 244 return precedenceAnd 245 } 246 case *And: 247 if len(f.Conjunct) == 0 { 248 return precedenceHigh // And{} == true 249 } else if len(f.Conjunct) == 1 { 250 return precedence(f.Conjunct[0], right) // And{f} == f 251 } else { 252 return precedenceAnd 253 } 254 case Not, Pred, Const, *Not, *Pred, *Const: 255 return precedenceHigh 256 default: 257 panic("not reached") 258 } 259 } 260 261 // formatFormWithParens outputs either f or (f), depending on how level compares 262 // to the precedence of f and whether f appears on the right side of a binary 263 // operator. 264 func formatFormWithParens(out fmt.State, level int, right bool, f Form, verb rune) { 265 if level > precedence(f, right) { 266 fmt.Fprint(out, "(") 267 f.Format(out, verb) 268 fmt.Fprint(out, ")") 269 } else { 270 f.Format(out, verb) 271 } 272 }